83
votes

How to I define the equivalent of this function (taken from learnyouahaskell) inside GHCi?

import Data.List  

numUniques :: (Eq a) => [a] -> Int  
numUniques = length . nub  

Without the type declaration, GHCi accepts the function definition, but it ends up with an unhelpful type:

Prelude Data.List> import Data.List 
Prelude Data.List> let numUniques' = length . nub
Prelude Data.List> :t numUniques'
numUniques' :: [()] -> Int

The resulting function only accepts a list of units as a parameter.

Is there a way provide type declarations in GHCi? Or is there another way to define functions like these which doesn't require type declarations?

I saw no obvious clues in the GHCi guide, and experimented with expressions like the following (to no avail):

> let numUniques' = ((length . nub) :: (Eq a) => [a] -> Int)
> :t numUniques'
numUniques' :: [()] -> Int
3

3 Answers

102
votes

Is there a way provide type declarations in GHCi?

let numUniques' :: (Eq a) => [a] -> Int; numUniques' = length . nub

Or is there another way to define functions like these which doesn't require type declarations?

If you turn off the monomorphism restriction with -XNoMonomorphismRestriction, it will infer the right type.

13
votes

Note that you can also avoid the monomorphism restriction simply by adding "points" (i.e. explicit variables) back to your expression. So this also gives the correct type:

let numUniques x = length . nub $ x

5
votes

The GHC User's Guide shows two additional ways to achieve this. This subsection introduces the :{ ... :} construct, which can be used as follows:

> :{
| numUniques :: (Eq a) => [a] -> Int
| numUniques = length . nub
| :}

Alternatively, you can enable multiline mode:

> :set +m
> let
| numUniques :: (Eq a) => [a] -> Int
| numUniques = length . nub
|