如何使用替代`代理::用`型的MyType A = Int`代理了`和`了`如幻影型
问题描述:
虽然与在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
,因为我不认为有任何歧义。我究竟做错了什么?
答
类型同义词与它们的扩展完全等价:R Int ~ R Bool ~ R Char ~ Int
。所以,你实际上是使用类型
f :: forall a. MyType a => Int -> Int
这本质上是模糊的,因为变量a
类型仅用于约束。
特别地,如果T
是data
或newtype
,则编译器可以简化型等式约束T a ~ T b
和推断a ~ b
。
对于类型族,这不再是真实的,因为它们可以是非内射的(虽然有一个GHC 8.0扩展可以正确处理注入)。
对于类型synomyms,这通常也是不正确的。鉴于T a ~ T b
我们扩大同义词T
继续进一步之前:如果a
和b
消失在这一步没有什么可以推断他们。
这是否意味着我必须在这里使用'data'或'newtype'? – rityzmon
@rityzmon我认为是这样,暂时。 – chi
谢谢。所以我很困惑。为什么当'a'不能使用时,编译器会允许一个类型同义词,比如'type R a = Int'? – rityzmon