我有以下方案的代码:
class First s where
func1 :: s -> s
class Second a where
func2 :: s -> a s
data D s = D {value :: s}
myFunc2 :: First s => s -> D s
myFunc2 = undefined
通常func2的参数不能是First的实例。我想在它的值为第一个实例的情况下制作第二个D实例。 然后我想得到这个实例:
instance Second D where
func2 = myFunc2
但是我收到了一个错误:
No instance for (First s)
arising from a use of `myFunc2'
好的,让实例是:
instance First s => Second D where
func2 = myFunc2
但这会产生错误:
Ambiguous constraint `First s'
At least one of the forall'd type variables mentioned by the constraint
must be reachable from the type after the '=>'
In the instance declaration for `Second D'
那么,有没有办法从其他类中获取具有某些条件的类实例,但是在'=>'之后没有所有类型变量?
答案 0 :(得分:7)
我认为通过
来定性思考是什么意思class Second a where
func2 :: s -> a s
Second
实例承诺为任何类型func2
定义s
。但myFunc2
并非如此,因为myFunc2
仅针对存在s
实例的First
定义。这意味着,由于您已定义First
和Second
,因此无法在myFunc2
实例中使用Second
(除非存在全部forall s . First s
实例,但我假设没有,或者你不会费心去制作类型类。)
所以,你必须改变至少一件事。你可以像Grzegorz建议的那样重新定义Second
。如果您不喜欢,可以重新定义Second
,如
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE FlexibleInstances #-}
class Second a s where
func2 :: s -> a s
instance First s => Second D s where
func2 = myFunc2
请注意,这与您最初写的内容有所不同,因为现在Second
实例并不保证func2
是多态的。但是我认为这更接近你所说的“当它是第一个值的实例时,只在那种情况下制作第二个实例”。也许它会在您的代码中被接受。
答案 1 :(得分:6)
确切的解决方案将取决于代码尝试执行的操作,但问题是您为func2
提供的类型签名未提及First s
约束,而您的定义为{{ 1}} func2
实例需要它。以下编译:
Second D