2016-05-31 30 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