type Cofree f a = Cofree a (f (Cofree f a)) type Functor f = Functor (forall a b. (a ->{} b) -> f a ->{} f b) use Functor Functor fmap : Functor f -> (a -> b) -> f a -> f b fmap fn f = match fn with Functor map -> map f use Cofree Cofree namespace Cofree where extract : Cofree f a -> a extract = cases Cofree a _ -> a duplicate : Functor f -> Cofree f a -> Cofree f (Cofree f a) duplicate f c = match c with Cofree a p -> Cofree c (fmap f (duplicate f) p)