haskelltypespointfreemonomorphism-restriction

Strange function type


I've a beginner's question about types in Haskell: Having a function like:

f i xs = (sort xs) !! i

How do I define the function f0 xs = f 0 xs without explicit use of xs? Just taking

f0 = f 0

does not work...

ghci shows me the folling types:
f :: Ord a => Int -> [a] -> a
f0 :: [()] -> ()
But ":t f 0" gives f 0 :: Ord a => [a] -> a.

Why is that? Why do I get this type for f0? Why is there any difference between the type of "f0" and the type of "f 0"?

Thanks a lot in advance for any suggestions


Solution

  • It has nothing to do with your particular definitions: if you do it (as you should!) with the standard implementation, the same thing happens.

    Prelude> let f0 = maximum
    Prelude> :t f0
    f0 :: [()] -> ()

    Anyway, first you should give f a signature.

    f :: Ord a => Int -> [a] -> a
    

    If you do that for f0 as well, all will work fine:

    f0 :: Ord a => [a] -> a
    

    Now the question is, why would ghci deduce such a stupid signature? It's the Dreaded Monomorphism Restriction's fault. That means, whenever you define something "as a constant(-applicative form)", i.e. a simple equation

    c = any odd stuff
    

    then the compiler refuses to give that automatically a polymorphic signature (like, with a type variables in it). Instead, it defaults to the "simplest usable" type, which for an Ord constraint unfortunately is the completely useless ().

    You can turn the monomorphism restriction off, then it'll work even without a signature:

    Prelude> :set -XNoMonomorphismRestriction
    Prelude> let f0 = maximum
    Prelude> :t f0
    f0 :: Ord a => [a] -> a

    But honestly, on the top level you should always use manual signatures anyway.