2016-05-31 14 views
1

雖然與在Haskell類型玩,我想出了以下內容:如何使用替代`代理::用`型的MyType A = Int`代理了`和`了`如幻影型

class MyType a where typeVal :: Proxy a -> Int 
instance MyType Int where typeVal _ = 1 
instance MyType Char where typeVal _ = 2 

g :: MyType a => Int -> Proxy a -> Int 
g x p = x + typeVal p 

這按預期工作。然後,我得到了我也許可以具備的功能到位返回自定義類型具有在Proxy傳遞的想法:我認爲這會工作

{-# LANGUAGE ScopedTypeVariables #-} 

type R a = Int 

f :: forall a. MyType a => Int -> R a 
f x = x + typeVal (Proxy :: Proxy a) 

但事實並非如此。我得到的錯誤:

Could not deduce (MyType a0) 
from the context (MyType a) 
    bound by the type signature for f :: MyType a => Int -> R a 
The type variable ‘a0’ is ambiguous 
In the ambiguity check for the type signature for ‘f’: 
    f :: forall a. MyType a => Int -> R a 
To defer the ambiguity check to use sites, enable AllowAmbiguousTypes 
In the type signature for ‘f’: f :: MyType a => Int -> R a 

我不想讓AllowAmbiguousTypes,因爲我不認爲有任何歧義。我究竟做錯了什麼?

回答

4

類型同義詞與它們的擴展完全等價:R Int ~ R Bool ~ R Char ~ Int。所以,你實際上是使用類型

f :: forall a. MyType a => Int -> Int 

這本質上是模糊的,因爲變量a類型僅用於約束。

特別地,如果Tdatanewtype,則編譯器可以簡化型等式約束T a ~ T b和推斷a ~ b

對於類型族,這不再是真實的,因爲它們可以是非內射的(雖然有一個GHC 8.0擴展可以正確處理注入)。

對於類型synomyms,這通常也是不正確的。鑑於T a ~ T b我們擴大同義詞T繼續進一步之前:如果ab消失在這一步沒有什麼可以推斷他們。

+1

這是否意味着我必須在這裏使用'data'或'newtype'? – rityzmon

+0

@rityzmon我認爲是這樣,暫時。 – chi

+0

謝謝。所以我很困惑。爲什麼當'a'不能使用時,編譯器會允許一個類型同義詞,比如'type R a = Int'? – rityzmon