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"可替代性",然后是类型a和b使用类型的"可统一性",c不幸的是更长.
EDIT(2)
哦抱歉.我认为你毕竟我已经说服了我,我必须重构代码,以便不会有任何错误定义的函数(即那些不包含其类型签名中所有独立类型的函数).和你说话确实让我想到了这件事.赞赏.
即使你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.仅仅因为您的代码不提供这样的类型.您的类型类的声明说,每对的类型a和b可能会得到一个实例.因此,即使a在调用中固定,foo仍然有任意多个可能的实例可供选择.
函数依赖a -> b将解决该问题,因为它指出:给定一个类型a,可能只有一个实例Foobar a b.相关类型通过不使用多参数类型类来避免该问题.
关于OP的编辑:
如果你坚持有两个类型参数.然后,类型类的每个方法的签名都必须包含类的每个类型变量.没有其他办法了.
如果你引入了一个函数依赖,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)
| 归档时间: |
|
| 查看次数: |
364 次 |
| 最近记录: |