Trident D'Gao
Trident D'Gao

Reputation: 19690

Why can't a type parameter be anything?

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

Answers (2)

wit
wit

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

daniel gratzer
daniel gratzer

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

Related Questions