Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Alias for a function name has a different type signature. Why?

Tags:

types

haskell

import Data.List (genericLength)

len = genericLength

:t genericLength
genericLength :: (Num i) => [b] -> i
:t len
len :: [b] -> Integer

Why is the type of len different from type of genericLength? The intent here is to use a shorter alias for genericLength.

Aren't functions first-class in haskell? Shouldn't giving another name for a function result in an identical function?

like image 913
Babu Srinivasan Avatar asked Jun 12 '11 04:06

Babu Srinivasan


1 Answers

What you're seeing here is because of a requirement that top-level declarations with no arguments be monomorphic. You can find some discussion of the reasons for this on the Haskell wiki, and some information about controlling this behavior in the GHC user's guide.

As illustration, note that giving len an argument fixes the problem:

len x = genericLength x

> :t len
len :: Num i => [b] -> i

So does giving it a type signature:

len :: (Num b) => [a] -> b
len = genericLength

And so does turning off the monomorphism restriction:

{-# LANGUAGE NoMonomorphismRestriction #-}
import Data.List (genericLength)

len = genericLength

> :t len
len :: Num i => [b] -> i

In this specific case, I think you're also getting a different type (rather than a compiler error) because of defaulting rules that specify that certain type classes should default to specific types (in this case, Num defaults to Integer. If you try doing the same thing with fmap you get this:

> :r
[1 of 1] Compiling Main             ( MonoTest.hs, interpreted )

MonoTest.hs:4:5:
    Ambiguous type variable `f0' in the constraint:
      (Functor f0) arising from a use of `fmap'
    Possible cause: the monomorphism restriction applied to the following:
      f :: forall a b. (a -> b) -> f0 a -> f0 b
        (bound at MonoTest.hs:4:1)
    Probable fix: give these definition(s) an explicit type signature
                  or use -XNoMonomorphismRestriction
    In the expression: fmap
    In an equation for `f': f = fmap
Failed, modules loaded: none.

You can find some information about defaulting in the Haskell 98 Report. I'll also mention that GHC supports an extended form of defaulting that's mostly used for GHCi (and is enabled there by default), which occasionally confuses people.

like image 160
C. A. McCann Avatar answered Sep 23 '22 01:09

C. A. McCann