Reputation: 19690
In my mind the type parameter a
can be anything including a list. Why can't this work?
fun :: a -> a
fun [] = []
Haskell doesn't want to compile this code. I wonder why.
Couldn't match expected type `a' with actual type `[t0]'
`a' is a rigid type variable bound by
the type signature for fun :: a -> a
I can make it work rewriting the signature like this
fun :: [a] -> [a]
But this is not something that I am looking for as I wanted to keep the function polymorphic.
I wonder how id
works on empty lists.
Prelude> :t id
id :: a -> a
Prelude> id []
[]
Upvotes: 1
Views: 180
Reputation: 1622
Let think, that it is possibe to write (it is not, but for fun):
fun :: a -> a
fun [] = []
This mean by pattern matching, that
fun _ = error "Nonwritten error!"
And this means next 2 things:
1) exists extra-data type, like:
data Universe = forall a. a
but this data don't exists in Haskell! And we have not data constructor here
2) this mean, that you signature is not right:
fun :: Universe -> Universe
Upvotes: 0
Reputation: 53881
A type variable can be anything, but you (the callee) don't get to choose what.
Let's detour into some terminology. Haskell defaults to what's called "universal quantification". This means that a given type variable may be satisfied by all instantiations. The caller may fill it with whatever they want.
So when you say
fun :: forall a. a -> a
fun [] = []
Is like saying, "for every possible type a
, treat it like a list", which obviously is nonsense!
It sounds like you want something more like adhoc polymorphism, which we use typeclasses for
{-# LANGUAGE OverlappingInstances, FlexibleInstances #-}
class Id a where
myId :: a -> a
instance Id a where
myId = id
instance Id [a] where
myId [] = [ undefined ] -- special case
myId xs = xs
Upvotes: 7