Creating polymorphic functions in Haskell
Here is how you can achieve something similar using type families.
Well if you have same return types then you can achieve the behaviour without using type families and just using type classes alone as suggested by Don.
But it is better to use type families when you want to support more complex adhoc polymorphism, like different return types for each instance.
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE TypeSynonymInstances #-}
{-# LANGUAGE TypeFamilies #-}
class F a where
type Out a :: *
f :: a -> Out a
instance F String where
type Out String = String
f = show . length
instance F Int where
type Out Int = String
f = show
instance F Float where
type Out Float = Float
f = id
In ghci
*Main> f (2::Int)
"2"
*Main> f "Hello"
"5"
*Main> f (2::Float)
2.0
There are two flavors of polymorphism in Haskell:
- parameteric polymorphism; and
- bounded polymorphism
The first is the most general -- a function is parametrically polymorphic if it behaves uniformly for all types, in at least one of its type parameters.
For example, the function length
is polymorphic -- it returns the length of a list, no matter what type is stored in its list.
length :: [a] -> Int
The polymorphism is indicated by a lower case type variable.
Now, if you have custom behavior that you want to have for a certain set of types, then you have bounded polymorphism (also known as "ad hoc"). In Haskell we use type classes for this.
The class declares which function will be available across a set of types:
class FunnyShow a where
funnyshow :: a -> String
and then you can define instances for each type you care about:
instance FunnyShow Int where
funnyshow i = show (i+1)
and maybe:
instance FunnyShow [Char] where
funnyshow s = show (show s)