具有Haskell功能依赖性的不明确类型变量

scr*_*avy 3 haskell types typeclass functional-dependencies

我正在使用Haskell的FunctionalDependencies-Extension以及MultiParamTypeClasses.我定义了以下内容:

class Add a b c | a b -> c where
    (~+) :: a -> b -> c
    (~-) :: a -> b -> c
    neg :: a -> a
    zero :: a
Run Code Online (Sandbox Code Playgroud)

哪个工作正常(我尝试过Int和Double的实例,最终目标是能够在没有显式转换的情况下添加Int和Doubles).

当我尝试为neg或(〜 - )定义默认实现时,如下所示:

class Add ...
    ...
    neg n = zero ~- n
Run Code Online (Sandbox Code Playgroud)

GHCi(7.0.4)告诉我以下内容:

Ambiguous type variables `a0', `b0', `c0' in the constraint:
  (Add a0 b0 c0) arising from a use of `zero'
Probable fix: add a type signature that fixes these type variable(s)
In the first argument of `(~-)', namely `zero'
In the expression: zero ~- n
In an equation for `neg': neg n = zero ~- n

Ambiguous type variable `a0' in the constraint:
  (Add a0 a a) arising from a use of `~-'
Probable fix: add a type signature that fixes these type variable(s)
In the expression: zero ~- n
In an equation for `neg': neg n = zero ~- n
Run Code Online (Sandbox Code Playgroud)

我想我确实理解这里的问题.GHC不知道使用哪个零,因为它可以是任何零,而这些任何东西反过来被输入到~-我们只知道的中,它有一个a正确的参数并产生一个a.

那么如何指定它应该是来自同一个实例的零,即如何表达如下内容:

neg n = (zero :: Add a b c) ~- n
Run Code Online (Sandbox Code Playgroud)

我认为a,bc这里是不是农行形成周边类,但任何AB和C,所以我怎么能表达一个类型,是为本地类型变量的引用?

dav*_*420 6

拉出negzero进入仅使用一种类型的超类:

class Zero a where
    neg :: a -> a
    zero :: a

class Zero a => Add a b c | a b -> c where
    (~+) :: a -> b -> c
    (~-) :: a -> b -> c
Run Code Online (Sandbox Code Playgroud)

问题的关键是你的方式,zero :: Int可能是zeroAdd Int Int Int,zeroAdd Int Double Double,并没有办法,两人之间的歧义无论你是从一个默认的实现或实例声明或正常代码中提到它的.

(您可能会反对zerofrom Add Int Int Intzerofrom Add Int Double Double将具有相同的值,但编译器无法知道某人不会Add Int Char Bool在不同的模块中定义并在zero那里给出不同的值.)

通过将类型类拆分为两个,我们消除了歧义.