Magasabb rangú típusok

Bevezetés

Bizonyos függvényterek egyszerűbb típusokkal izomorfak:

--  Bool -> a              ~  (a, a)
--  a -> a                 ~  ()
--  Stream a -> a          ~  Nat
--  (a -> a) -> (a -> a)   ~  ?

Motiváló példa: Church számok

Megoldás:

--  (a -> a) -> (a -> a)   ~  Nat

Az izomorfiát biztosító függvények:

ch :: Int -> (a->a)->(a->a)
ch i f = (!!i) . iterate f
-- eval :: ((a->a)->(a->a)) -> Int
eval f = f (+1) 0

Második rangú típusok

Egy fokkal általánosabb típus (lásd később):

eval :: (forall a. (a->a)->(a->a)) -> Int

Nevezzük el a típust:

type ChurchNum = forall a . (a -> a) -> (a -> a)       

Nyelvi támogatás

A Haskell98-ban nincsenek magasabb rangú típusok. A következő két kiterjesztés valamelyike szükséges a Church számok megfelelő reprezentációjához:

{-# LANGUAGE Rank2Types #-}

vagy

{-# LANGUAGE RankNTypes #-}

Műveletek

Három művelet:

add, mul, pow :: ChurchNum -> ChurchNum -> ChurchNum 
add f g x = f x . g x
mul f g = f . g
pow f g = g f

Második rangú típusok nélkül a fenti típusozás lehetetlen.

church_test = and
    [ ch 5 (++"X") "alma" == "almaXXXXX"
    , eval (ch 5) == 5
    , eval (add (ch 5) (ch 6)) == 11
    , eval (mul (ch 5) (ch 6)) == 30
    , eval (pow (ch 5) (ch 6)) == 15625
    ]