Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Ambiguous type variable but not in ghci?

Tags:

haskell

Can anybody explain why haskell enforces explicit type signature in the following example and how to modify it to avoid need of the explicit declaration ?

import qualified Data.List as L

main = do
    print $ length $ L.nub [1,1,2,3]  -- 3, passed (Eq a, Num a) => [a]
    print $ length $ L.nub []         -- ambiguous type error, passed (Eq a) => [a]
    -- can help type system with explicit signature but how to avoid ?
    print $ length $ L.nub ([] :: [Int])

Surprisingly the same code written interactively in ghci has no issue with ambiguity and does prints zero length:

λ> :m +Data.List
λ> print $ length $ nub []
0  -- ?? can you explain ??

Update: It seems even same restricted as Data.List.nub length function won't stop complaints about ambiguous type:

length' :: Eq a => [a] -> Int
length' [] = 0
length' (x:xs) = 1 + length' xs

main = do
    print $ length' $ nub []
-- No instance for (Eq a0) arising from a use of ‘length'’
-- The type variable ‘a0’ is ambiguous
like image 707
David Unric Avatar asked Oct 20 '14 13:10

David Unric


1 Answers

The problem is that [] has the polymorphic type (Eq a) => [a]. Since length doesn't add any particular constraint.

Specifically the type of length is:

length :: [a] -> Int

which is even more permissive than nub:

nub :: Eq a => [a] -> [a]

The compiler needs to use a specific instance of length there and is not able to deduce a type for a.

Now you have two options:

  1. Turn on the ExtendedDefaultRules extension with {-# LANGUAGE ExtendedDefaultRules #-} at the beginning of the file.
  2. Be explicit: ... L.nub ([] :: [Int])

I'd recommend the 2nd one by default, unless you fully understand the consequences of the first one.

like image 194
Shoe Avatar answered Oct 20 '22 21:10

Shoe