1

In the following code, I get the error

Couldn't match type 'Integer' with 'Int'
Expected type :[(Test, [Test])]
Actual type : [(Integer, [Integer])]

when executing

testFunc test

with the following declaration

type TestType = Int
a = [(1,[2,3])]

testFunc :: [(TestType ,[TestType])] -> TestType 
testFunc ((a,(b:c)):d) = a

How do I declare my list a so that it matches the type of testFunc?

And is there a way to fix the error without modifying type Test = Int or the declaration of a?

Micha Wiedenmann
  • 19,979
  • 21
  • 92
  • 137
user3548298
  • 186
  • 1
  • 1
  • 13

1 Answers1

4

How do I declare my list 'test' so that it matches the type of testFunc?

Well, by declaring this as the type.

a :: [(TestType, [TestType])]
a = [(1,[2,3])]

Generally speaking, you should always give explicit type signatures for top-level definitions like this. Without such a signature, the compiler will pick one for you. Generally Haskell tries to pick the most general available type possible; in this case that would be

a :: (Num a, Num b) => [(a, [b])]

...which would include both [(Int, [Int])] and [(Integer, [Integer])]. However, the monomorphism restriction restricts the type by default, excluding such polymorphism. So GHC has to pick one version, and the default one is Integer, not Int.

The right solution, again, is to provide an explicit signature. However, you can also turn off the monomorphism restriction:

{-# LANGUAGE NoMonomorphismRestriction #-}

type TestType = Int
a = [(1,[2,3])]

testFunc :: [(TestType ,[TestType])] -> TestType 
testFunc ((x,(y:z)):w) = x

main :: IO ()
main = print $ testFunc a
leftaroundabout
  • 117,950
  • 5
  • 174
  • 319
  • 1
    The `{-# LANGUAGE NoMonomorphismRestriction #-}` isn't necessary in your last example; the same code works just fine without it. When you call `testFunc a` in the same source file that you define `a`, then the monomorphism restriction infers `a :: [(TestType, [TestType])]`. The monomorphism restriction won't pick `Integer` over `Int` if the only use sites require `Int`, as in your example. I suspect the OP was calling the function in GHCi after loading a file containing `testFunc` and `a`. – Ben Mar 14 '19 at 03:56
  • @Ben interesting, I actually didn't know that it does that over top-level bindings. This isn't something I would ever rely on though – moving that definition to another module would change the type inference! Better always give a signature. – leftaroundabout Mar 14 '19 at 11:43
  • I definitely agree that the right solution is to give a type signature. – Ben Mar 14 '19 at 23:07