Zoeken…


Opmerkingen

Functies die hier in voorbeelden worden genoemd, worden in verschillende pakketten gedefinieerd met verschillende mate van abstractie, bijvoorbeeld data-fix en recursion-schemes (meer functies hier). U kunt een completere lijst bekijken door op Hayoo te zoeken .

Vaste punten

Fix neemt een "sjabloon" type en bindt de recursieve knoop, waarbij de sjabloon als een lasagne wordt gelaagd.

newtype Fix f = Fix { unFix :: f (Fix f) }

Binnen een Fix f vinden we een laag van de sjabloon f . Invullen f 's parameter Fix f pluggen op zich. Dus als u in de sjabloon f kijkt, vindt u een recursief voorkomen van Fix f .

Hier is hoe een typisch recursief datatype kan worden vertaald in ons raamwerk van sjablonen en vaste punten. We verwijderen recursieve gebeurtenissen van het type en markeren hun posities met de parameter r .

{-# LANGUAGE DeriveFunctor #-}

-- natural numbers
-- data Nat = Zero | Suc Nat
data NatF r = Zero_ | Suc_ r deriving Functor
type Nat = Fix NatF

zero :: Nat
zero = Fix Zero_
suc :: Nat -> Nat
suc n = Fix (Suc_ n)


-- lists: note the additional type parameter a
-- data List a = Nil | Cons a (List a)
data ListF a r = Nil_ | Cons_ a r deriving Functor
type List a = Fix (ListF a)

nil :: List a
nil = Fix Nil_
cons :: a -> List a -> List a
cons x xs = Fix (Cons_ x xs)


-- binary trees: note two recursive occurrences
-- data Tree a = Leaf | Node (Tree a) a (Tree a)
data TreeF a r = Leaf_ | Node_ r a r deriving Functor
type Tree a = Fix (TreeF a)

leaf :: Tree a
leaf = Fix Leaf_
node :: Tree a -> a -> Tree a -> Tree a
node l x r = Fix (Node_ l x r)

Een structuur laag voor laag opvouwen

Catamorfismen , of plooien , modelleren primitieve recursie. cata tranen in een plaatsbepalingspunt laag voor laag, via een algebra functie (of vouwen functie) aan elke laag te verwerken. cata vereist een Functor instantie voor het sjabloontype f .

cata :: Functor f => (f a -> a) -> Fix f -> a
cata f = f . fmap (cata f) . unFix

-- list example
foldr :: (a -> b -> b) -> b -> List a -> b
foldr f z = cata alg
    where alg Nil_ = z
          alg (Cons_ x acc) = f x acc

Een structuur laag voor laag ontvouwen

Anamorfismen , of ontvouwt zich , modelleert primitieve corecursie. ana bouwt een plaatsbepalingspunt laag voor laag, via een coalgebra functie (of ontvouwen functie) aan elke nieuwe laag te produceren. ana vereist een Functor instantie voor het sjabloontype f .

ana :: Functor f => (a -> f a) -> a -> Fix f
ana f = Fix . fmap (ana f) . f

-- list example
unfoldr :: (b -> Maybe (a, b)) -> b -> List a
unfoldr f = ana coalg
    where coalg x = case f x of
                         Nothing -> Nil_
                         Just (x, y) -> Cons_ x y

Merk op dat ana en cata dubbel zijn . De typen en implementaties zijn spiegelbeelden van elkaar.

Uitvouwen en vervolgens vouwen, gefuseerd

Het is gebruikelijk om een programma te structureren als het opbouwen van een gegevensstructuur en deze vervolgens samen te vouwen tot een enkele waarde. Dit wordt een hylomorfisme of hervouwen genoemd . Het is mogelijk om de tussenliggende structuur helemaal te elimineren voor verbeterde efficiëntie.

hylo :: Functor f => (a -> f a) -> (f b -> b) -> a -> b
hylo f g = g . fmap (hylo f g) . f  -- no mention of Fix!

Afleiding:

hylo f g = cata g . ana f
         = g . fmap (cata g) . unFix . Fix . fmap (ana f) . f  -- definition of cata and ana
         = g . fmap (cata g) . fmap (ana f) . f  -- unfix . Fix = id
         = g . fmap (cata g . ana f) . f  -- Functor law
         = g . fmap (hylo f g) . f  -- definition of hylo

Primitieve recursie

Paramorfismen modelleren primitieve recursie. Bij elke iteratie van de vouw ontvangt de vouwfunctie de substructuur voor verdere verwerking.

para :: Functor f => (f (Fix f, a) -> a) -> Fix f -> a
para f = f . fmap (\x -> (x, para f x)) . unFix

De tails de Prelude kunnen worden gemodelleerd als een paramorfisme.

tails :: List a -> List (List a)
tails = para alg
    where alg Nil_ = cons nil nil  -- [[]]
          alg (Cons_ x (xs, xss)) = cons (cons x xs) xss  -- (x:xs):xss

Primitieve corecursie

Apomorfismen modelleren primitieve corecursie. Bij elke iteratie van het ontvouwen, kan de ontvouwende functie ofwel een nieuw zaad of een hele subtree teruggeven.

apo :: Functor f => (a -> f (Either (Fix f) a)) -> a -> Fix f
apo f = Fix . fmap (either id (apo f)) . f

Merk op dat apo en para dubbel zijn . De pijlen in het type zijn omgedraaid; de tuple in para is tweeledig ten opzichte van Either in apo , en de implementaties zijn spiegelbeelden van elkaar.



Modified text is an extract of the original Stack Overflow Documentation
Licentie onder CC BY-SA 3.0
Niet aangesloten bij Stack Overflow