Skip to content

Instantly share code, notes, and snippets.

@sjoerdvisscher
Last active May 3, 2024 10:49
Show Gist options
  • Save sjoerdvisscher/962302a5e874b28cd5e97d49d08b3063 to your computer and use it in GitHub Desktop.
Save sjoerdvisscher/962302a5e874b28cd5e97d49d08b3063 to your computer and use it in GitHub Desktop.
Cofree j-relative comonad
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE PolyKinds #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE DeriveFunctor #-}
{-# LANGUAGE StandaloneDeriving #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE FlexibleInstances #-}
module Cofreer where
import Data.Kind (Type)
import Data.Functor.Identity
class RelComonad j w where
extract :: w a -> j a
extend :: (w a -> j b) -> w a -> w b
data Cofreer :: (k -> Type) -> (k -> Type) -> k -> Type where
Cofreer :: j a -> (forall b. (Cofreer j f a -> j b) -> f b) -> Cofreer j f a
deriving instance (Functor j, Functor f) => Functor (Cofreer j f)
instance RelComonad j (Cofreer j f) where
extract (Cofreer j _) = j
extend h w@(Cofreer j f) = Cofreer (h w) (\k -> f (k . extend h))
data Cofree f a = a :< f (Cofree f a)
toCofree :: Cofreer Identity f a -> Cofree f a
toCofree (Cofreer (Identity a) g) = a :< g (Identity . toCofree)
fromCofree :: Functor f => Cofree f a -> Cofreer Identity f a
fromCofree (a :< fc) = Cofreer (Identity a) (\g -> fmap (runIdentity . g . fromCofree) fc)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment