如何摆脱这种模棱两可?

jul*_*icz 7 haskell type-systems functional-programming ambiguity ghc

我很确定以前曾经问过,但是我找不到正确的答案:

我试图消除以下示例代码段中的歧义:

{-# LANGUAGE MultiParamTypeClasses #-}

class FooBar a b where
    foo :: a -> a
    foo = id
    bar :: a -> a
    bar = foo        -- ERROR AT THIS LINE
Run Code Online (Sandbox Code Playgroud)

我收到如下错误消息:

Ambiguous type variable `b0' in the constraint:
      (FooBar a b0) arising from a use of `foo'
    Probable fix: add a type signature that fixes these type variable(s)
    In the expression: foo
    In an equation for `bar': bar = foo
Run Code Online (Sandbox Code Playgroud)

这是可以理解的.但请注意,我实际上无法遵循编译器的建议并修复有问题的类型变量:在其类型签名foo中不包含b类型变量.这也行不通:

    bar = (foo :: FooBar a b => a -> a) -- ERROR, the same error message
Run Code Online (Sandbox Code Playgroud)

甚至没有-XScopedTypeVariables启用.

如何告诉GHC FooBar使用哪个?它甚至可能吗?

编辑

回答一下:是的,我听说过功能依赖和相关类型.

至于功能依赖 - 我正在寻找一种方法来明确告知GHC使用哪个实例(而不是要求它自己导出正确的类型).

至于两者 - 在现实世界的例子中,我实际上需要两个参数a并且b是独立的.

再说一遍:我知道这个例子非常愚蠢,我知道b不是在类类的主体中使用,这没有任何意义.这是对现实世界示例的极端简化,实际上确实有意义.真实的用例涉及a使用类型的类型的b"可替代性",然后是类型ab使用类型的"可统一性",c不幸的是更长.

EDIT(2)

哦抱歉.我认为你毕竟我已经说服了我,我必须重构代码,以便不会有任何错误定义的函数(即那些不包含其类型签名中所有独立类型的函数).和你说话确实让我想到了这件事.赞赏.

jmg*_*jmg 8

即使你bar完全从班级中删除,你的班级也是不明确的.我们假设你有以下课程:

class FooBar a b
  where
    foo :: a -> a
    foo = id
Run Code Online (Sandbox Code Playgroud)

假设您现在想要foo在此类的定义之外使用.

e = .... foo x .....
Run Code Online (Sandbox Code Playgroud)

GHC会抱怨类似的错误消息比你的错误,它无法找到类型b.仅仅因为您的代码不提供这样的类型.您的类型类的声明说,每对的类型ab可能会得到一个实例.因此,即使a在调用中固定,foo仍然有任意多个可能的实例可供选择.

函数依赖a -> b将解决该问题,因为它指出:给定一个类型a,可能只有一个实例Foobar a b.相关类型通过不使用多参数类型类来避免该问题.

关于OP的编辑:

如果你坚持有两个类型参数.然后,类型类的每个方法的签名都必须包含类的每个类型变量.没有其他办法了.


Dan*_*her 6

如果你引入了一个函数依赖,class FooBar a b | a -> b where那将解决它,但没有它(或相关类型),我认为不可能解析要使用的实例.

哦,一种方式,但有点丑:引入类型b的虚拟参数

class FooBar a b where
    foo' :: b -> a -> a
    foo' _ = id
    bar' :: b -> a -> a
    bar' b = foo b
Run Code Online (Sandbox Code Playgroud)

  • 我发现一个hack比添加一个类型为`b`的虚拟参数稍微不那么难看,就是要有`data Proxy a = Proxy`然后添加一个类型为`Proxy b`的虚拟参数.它避免了凌乱的"井,'未定义'是可以的,因为函数永远不会看它"推理. (4认同)