
On Sunday 26 September 2010 22:46:35, Russ Abbott wrote:
The following runs without a problem.
Prelude> let null' xs = xs == [] null' :: (Eq a) => [a] -> Bool
Prelude> let main' = do print (null' []) main' :: IO ()
Prelude> main' True it :: ()
But if I put essentially the same code in a file and try to load the file I get an error.
File: Null
null' xs = xs == []
main = do print (null' [])
Prelude> :load "Null.hs" [1 of 1] Compiling Main ( Null.hs, interpreted )
Null.hs:3:17: Ambiguous type variable `a' in the constraint: `Eq a' arising from a use of `null'' at Null.hs:3:17-24 Probable fix: add a type signature that fixes these type variable(s) Failed, modules loaded: none.
Why is that?
ghci has extended defaulting rules, a lot of things have their type defaulted to avoid too many "Ambiguous type variable ..." messages at the prompt although per the report they shouldn't be defaulted. When a source file is compiled (whether to object code or to bytecode), the defaulting rules of the report are applied. The expression "null' []" has the ambiguous type Eq a => [a] -> Bool (there's no way to determine at which type the expression should be evaluated). The defaulting rules in the language report, http://www.haskell.org/onlinereport/haskell2010/haskellch4.html#x10-790004.3... say such an ambiguity can be resolved by defaulting under certain cirumstances, a necessary condition is that there is one numeric type class constraint. That isn't the case here, so defaulting isn't allowed, compilation fails. At the prompt, ghci merrily resolves the ambiguity by defaulting a to ().
I had thought that the ambiguity was referring to the type of [] in the print statement, i.e., that GHC can't figure out the type of []. If I modify the print statement to be print ( null' ([] :: [Int]) ) everything is ok.
Right.
But if that's the case, why is this not a problem at the interactive level?
Extended defaulting rules, because otherwise there would be too many ambiguity errors. At the prompt, most expressions you enter have very little context which would allow to determine a type, in source files there's usually much more context available, so ambiguities are less frequent in code.
Here is a related question. In the following what does it mean to say that x is of type [a] where "a" is a type variable?
Prelude> let x = [] x :: [a]
It means x is a polymorphic expression, x can belong to every list type. Prelude> ([x,[True]],[x,"ah"],[x,[fromEnum 'u']]) ([[],[True]],["","ah"],[[],[117]]) It can even appear at different types in the same expression.
For example,
Prelude> x == (tail [1 :: Int]) True it :: Bool
Prelude> x == (tail [1 :: Float]) True it :: Bool
Prelude> (tail [1 :: Int]) == (tail [1 :: Float])
<interactive>:1:28: Couldn't match expected type `Int' against inferred type `Float' In the expression: 1 :: Float In the first argument of `tail', namely `[1 :: Float]' In the second argument of `(==)', namely `(tail [1 :: Float])'
Can a value like the value of x really be of an incompletely specified type?
Yes, that's possible. [], Nothing and others have this property. Although, it would be more correct to say that x can be instantiated at different types.
I couldn't do that in the file.
You can, but there are a few things that can prevent it. One is the monomorphism restriction (aka the dreaded MR).
When I tried the following in the file,
print (null' ([] :: (Eq a) => a))
I got this error message on loading the file.
Null.hs:3:24: Couldn't match expected type `a1' against inferred type `[a]' `a1' is a rigid type variable bound by an expression type signature at Null.hs:3:34 In the first argument of `null'', namely `([] :: (Eq a) => a)' In the first argument of `print', namely `(null' ([] :: (Eq a) => a))' In the expression: print (null' ([] :: (Eq a) => a))
Yes, that's not very illuminating at first. The point of this message is that you said [] could have any type, as long as it belongs to Eq, in particular, it could be Bool. However, the most general type of [] is [a], so it could be any type, as long as it's a list type - Bool isn't, so you have the type mismatch, the promised type (Eq a) => a versus the inferred type [b]. If you fix that and write print (null' ([] :: (Eq a) => [a])) You'll get a different error, the one you got before you added the expression type signature: Ambiguous type variable `b' in the constraint: `Eq b' arising from an expression type signature at TTest.hs:3:22-40 Probable fix: add a type signature that fixes these type variable(s)
Thanks.
-- Russ