Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Inference of if ... then ... else strange behaviour

Considering the following bad code :

fun x = 
    if (null x) then 0
    else (take 50 x) : (fun (drop 50 x)) 

I noticed, I can load it into ghci without any problem, and that's the problem.
The program only retrieve me an error when i try to evaluate this function.

Regarding the default inference rule of if ... then ... else expression, as the two branches explicitly retrieve different type, why this code can be load (ie compiled) ? I mean, why the compiler can't figured out this code is ill-formed ?

Note : Of course if i add the correct type annotation for this function, as expected it'll be rejected, but in my understanding it should be rejected too without the type annotation.

like image 667
zurgl Avatar asked Dec 01 '22 21:12

zurgl


1 Answers

Overloaded numeric literals. Haskell numeric literals are instances of whatever Num classes are defined, based on the type context.

The inferred type explains it:

Prelude> let f x = if null x then 0 else take 50 x : f (drop 50 x)

Prelude> :t f
f :: Num [[a]] => [a] -> [[a]]

That reads as "if you have an instance of the Num class for lists of lists of a, then this function takes a list of a to a list of list of a.

So it relies on a mythical instance of Num for lists of lists. If you tried to compile code that used this, without providing an instance of numbers for lists of lists, it would be a compilation error.

This example also illustrates why it is a good idea to write down the type signature first.

like image 63
Don Stewart Avatar answered Dec 04 '22 02:12

Don Stewart