简体   繁体   English

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

[英]Ambiguous type variables in Haskell when using multiple parameter type classes

I'm struggling with ambiguous type variables in typeclasses in Haskell: 我正在努力处理Haskell中类型类中的模糊类型变量:

This code boils down my problem to the basics: 这段代码将我的问题归结为基础知识:

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)

It doesn't compile, saying that the type variables that I'm not using when I call foo and bar are ambiguous: 它没有编译,说当我调用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)

It works when I have three separate type classes for foo, bar and baz, and define solve as: 当我有foo,bar和baz的三个独立类型类时,它可以工作,并将resolve定义为:

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

But this is very cumbersome. 但这非常麻烦。 Why do I have these three functions in one typeclass in the first place? 为什么我首先在​​一个类型类中包含这三个函数? Well they're all related and I always use all three together. 好吧,他们都是相关的,我总是把三者都用在一起。

I've tried putting type signatures around foo and bar and using forall (admittedly, somewhat at random through desperation). 我已经尝试在foo和bar周围放置类型签名并使用forall(诚然,通过绝望有点随意)。 I've looked at the existing ambiguous type variable questions and don't see a fix that is relevant to me. 我查看了现有的模糊类型变量问题,并没有看到与我相关的修复。

How can I solve this? 我怎么解决这个问题?

Thanks very much. 非常感谢。

From the use of foo, the compiler can't know which instance of Problem to choose. 从使用foo开始,编译器无法知道要选择哪个Problem实例。 There might be several instances with the same a but different b s. 有可能是用相同的多个实例a但不同b秒。 You can tell the compiler that this isn't the case with functional dependencies, but in this case I think there's a simpler solution: 你可以告诉编译器这不是函数依赖的情况,但在这种情况下我认为有一个更简单的解决方案:

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

Then the type for solve is clean: 然后解决的类型是干净的:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM