简体   繁体   中英

Creating polymorphic functions in Haskell

A short search didn't help me to find the answer, so I started to doubt in its existance. The question is simple. I want to create a polymorphic function, something like this:

f :: String -> String
f s = show (length s)

f :: Int -> String
f i = show i

A function defined differently for different data types is meant. Is it possible? If yes, how?

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)

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM