3
votes

I have this code that does not compile. I'd like to understand why it can not deduce the types.

module Main where

data Combiner a = Combiner a (a -> Int)
comb = Combiner 3 (\x -> 5)

class HasValue a where
  getValue :: Int

instance HasValue Combiner where
  getValue (Combiner x f) = f x

main = print $ getValue comb

Here's the error:

main.hs:8:3: error:
• Could not deduce (HasValue a0)
  from the context: HasValue a
    bound by the type signature for:
               getValue :: HasValue a => Int
    at main.hs:8:3-17
  The type variable ‘a0’ is ambiguous
• In the ambiguity check for ‘getValue’
  To defer the ambiguity check to use sites, enable AllowAmbiguousTypes
  When checking the class method:
    getValue :: forall a. HasValue a => Int
  In the class declaration for ‘HasValue’
1
Shouldn't the signature of getValue be a -> Int?Willem Van Onsem
it is probably not the only error. Sometimes it makes sense to start with the first onemax630

1 Answers

6
votes

Given I understand it correctly, you defined the wrong signature for getValue. Now it is defined:

class HasValue a where
  getValue :: Int

So that means there can be different versions of getValue, but since these all return an Int, it is completely impossible to know which instance we want to pick.

Based on the instance declaration later in the file (and the name of the function) however, I think you were actually looking for:

class HasValue a where
  getValue :: a -> Int

Now Haskell can derive the a from the type of the parameter of the function application. Furthermore this also matches with your function body in the instance HasValue.

Furthermore the Combiner is not a monotype, so we need to add the type parameter in the head:

instance HasValue (Combiner a) where
  getValue (Combiner x f) = f x