Haskell:在另一个实例中使用一个类

时间:2012-03-15 04:58:35

标签: haskell

我有以下方案的代码:

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'

那么,有没有办法从其他类中获取具有某些条件的类实例,但是在'=>'之后没有所有类型变量?

2 个答案:

答案 0 :(得分:7)

我认为通过

来定性思考是什么意思
class Second a where
    func2 :: s -> a s

Second实例承诺为任何类型func2定义s。但myFunc2并非如此,因为myFunc2仅针对存在s实例的First定义。这意味着,由于您已定义FirstSecond,因此无法在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