使用多个参数类型类时Haskell中的模糊类型变量

时间:2011-09-05 11:50:09

标签: haskell

我正在努力解决Haskell中类型类中的模糊类型变量:

此代码将我的问题归结为基础知识:

class Problem a b where
    foo :: a -> a
    bar :: b -> b
    baz :: a -> b -> (a, b)

solve :: Problem a b => a -> b -> (a, b)
solve a b = baz (foo a) (bar b)

它没有编译,说当我调用foo和bar时我没有使用的类型变量是不明确的:

    Ambiguous type variable `b0' in the constraint:
      (Problem a b0) arising from a use of `foo'
    Probable fix: add a type signature that fixes these type variable(s)
    In the first argument of `baz', namely `(foo a)'
    In the expression: baz (foo a) (bar b)
    In an equation for `solve': solve a b = baz (foo a) (bar b)

    Ambiguous type variable `a0' in the constraint:
      (Problem a0 b) arising from a use of `bar'
    Probable fix: add a type signature that fixes these type variable(s)
    In the second argument of `baz', namely `(bar b)'
    In the expression: baz (foo a) (bar b)
    In an equation for `solve': solve a b = baz (foo a) (bar b)

当我有foo,bar和baz三个单独的类型,并将solve定义为:

solve :: FooProblem a => BarProblem b => BazProblem a b => a -> b -> (a, b)

但这非常麻烦。为什么我首先在​​一个类型类中包含这三个函数?好吧,他们都是相关的,我总是把三者都用在一起。

我已经尝试在foo和bar周围放置类型签名并使用forall(诚然,通过绝望有点随意)。我查看了现有的模糊类型变量问题,并没有看到与我相关的修复。

我该如何解决这个问题?

非常感谢。

1 个答案:

答案 0 :(得分:7)

从使用foo开始,编译器无法知道要选择哪个Problem实例。可能存在多个具有相同a但不同b的实例。你可以告诉编译器这不是函数依赖的情况,但在这种情况下我认为有一个更简单的解决方案:

class (FooProblem a, BarProblem b) => BazProblem a b where
  baz :: a -> b -> (a, b)

然后解决的类型是干净的:

solve :: BazProblem a b => a -> b -> (a, b)