2015-08-30 9 views
13
data Tree t = Empty | Node t (Tree t) (Tree t) 

Siamo in grado di creare l'istanza Functor e utilizzareFunctional albero e pieghevole ma con nodi. C'è qualche generalizzazione su di esso?

fmap :: (t -> a) -> Tree t -> Tree a 

Ma cosa succede se, invece di (t -> a) che voglio (Albero t -> a) in modo da poter avere accesso a un intero (Nodo t) non solo t

treeMap :: (Tree t -> a) -> Tree t -> Tree a 
treeMap f Empty = Empty 
treeMap f [email protected](Node _ l r) = Node (f n) (treeMap f l) (treeMap f r) 

Stessa cosa con piega

treeFold :: (Tree t -> a -> a) -> a -> Tree t -> a 

c'è qualche generalizzazione oltre func cose come queste?

map :: (f t -> a) -> f t -> f a 
fold :: (f t -> a -> a) -> a -> f t -> a 

risposta

14

Hai appena scoperto le comonad! Be 'quasi.

class Functor f => Comonad f where 
    extract :: f a -> a 
    duplicate :: f a -> f (f a) 

instance Comonad Tree where 
    extract (Node x _ _) = x -- this one only works if your trees are guaranteed non-empty 
    duplicate [email protected](Node n b1 b2) = Node t (duplicate b1) (duplicate b2) 

Con duplicate è possibile implementare le funzioni:

treeMap f = fmap f . duplicate 
freeFold f i = foldr f i . duplicate 

per farlo correttamente, si dovrebbe far rispettare non emptyness dal sistema tipo:

type Tree' a = Maybe (Tree'' a) 

data Tree'' t = Node' t (Tree' t) (Tree' t) 
    deriving (Functor) 

instance Comonad Tree'' where 
    extract (Node' x _ _) = x 
    duplicate [email protected](Node' _ b1 b2) = Node' t (fmap duplicate b1) (fmap duplicate b2) 
Problemi correlati