Haskell's ambiguous type variables when using multiple parameter type classes

I am struggling with ambiguous type variables in classes in Haskell:

This code brings my problem to the basics:

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

It does not compile, saying that type variables that I do not use when calling foo and bar are ambiguous:

  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 ab = 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 ab = baz (foo a) (bar b) 

This works when I have three separate class classes for foo, bar and baz, and define the solution as:

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

But it is very cumbersome. Why do I have these three functions in one class? Well, they are all connected, and I always use all three together.

I tried putting type signatures around foo and bar and using forall (admittedly somewhat randomly through desperation). I looked over existing ambiguous type variables and don’t see the fix that matters to me.

How can i solve this?

Many thanks.

+6
source share
1 answer

From using foo, the compiler cannot know which instance of the problem to select. There may be several instances with the same a , but with different b s. You can tell the compiler that this does not apply to functional dependencies, but in this case I find there a simpler solution:

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

Then the type for the solution is clean:

 solve :: BazProblem ab => a -> b -> (a, b) 
+7
source

Source: https://habr.com/ru/post/896636/


All Articles