我正在研究一个monadic流库,并且遇到了一个我不明白的类型的东西。我已经成功将其降低到下面的例子:用类型相等约束修复的模糊类型变量
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE TypeFamilies #-}
class Foo a b where
type E a b :: *
(>->) :: a -> b -> E a b
data Bar x
instance Foo (Bar x) (Bar x) where
type E (Bar x) (Bar x) = Bar x
(>->) = undefined
x = undefined :: Bar a
y = undefined :: Bar Int
z = x >-> y
当我尝试编译它,我得到:
No instance for (Foo (Bar a0) (Bar Int))
arising from a use of ‘>->’
The type variable ‘a0’ is ambiguous
Relevant bindings include
z :: E (Bar a0) (Bar Int)
(bound at /usr/local/google/home/itaiz/test/test.hs:17:1)
Note: there is a potential instance available:
instance Foo (Bar x) (Bar x)
-- Defined at /usr/local/google/home/itaiz/test/test.hs:10:10
In the expression: x >-> y
In an equation for ‘z’: z = x >-> y
这,我猜,我惊讶了一下,但也许不是太许多。什么确实让我感到吃惊的是,如果我用下面的那么一切替换该实例的工作原理:
instance (x ~ x') => Foo (Bar x) (Bar x') where
type E (Bar x) (Bar x') = Bar x
(>->) = undefined
我没有看到这两个实例声明之间的区别。我猜这跟类型变量的作用域有关。有人可以解释发生了什么吗?
旁白:我看到同样的事情用fundeps时代替。]
我相信第二种形式是有效的,而第一种形式没有效果,因为在第二种形式中,您有'x〜x'的约束。然后这个约束可以让类型检查器找出'a〜Int',而没有这个约束它只是看不到'Foo(Bar a)(Bar Int)'的实例。如果你使用第一种形式,然后有'z =(x :: Bar Int)> - > y',它就编译。 – bheklilr 2014-10-01 17:31:27