Skip to content

robrix/freer-cofreer

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

freer-cofreer: freer monads and cofreer comonads.

This is an implementation of the Freer monad described by Oleg Kiselykov in Free and Freer Monads: Putting Monads Back in the Closet, and the Cofreer comonad, defined by analogy with Freer.

Freer and Cofreer differentiate themselves from Free and Cofree by admitting Functor & Monad/Comonad instances even when the signature is not a Functor. This makes them particularly suitable for working with certain GADTs. For example:

data PromptF a where
  Write :: String -> PromptF ()
  Read :: PromptF String

type Prompt = Freer PromptF

write :: String -> Prompt ()
write s = Write s `Then` Return

read :: Prompt String
read = Read `Then` Return

greeting :: Prompt ()
greeting = do
  write "Hi! What’s your name?\n"
  name <- read
  write $ "Pleased to meet you, " ++ name ++ "!"

runPrompt :: Prompt a -> IO a
runPrompt = iterFreer (\ yield instruction -> case instruction of
  Write s -> putStrLn >>= yield
  Read -> getLine >>= yield)

The constraints placed on the constructors of PromptF mean that it doesn’t admit a Functor instance, and thus is not very useful with Free. With Freer, you get Functor, Applicative, and Monad instances with PromptF “for free,” complete with the majority of the API defined in Control.Monad.Free.Freer.

About

freer monads and cofreer comonads.

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published