Skip to content

Instantly share code, notes, and snippets.

@pepegar
Last active September 14, 2016 08:31
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save pepegar/097c0c321bfa80d3fa3c92b81ad71acf to your computer and use it in GitHub Desktop.
Save pepegar/097c0c321bfa80d3fa3c92b81ad71acf to your computer and use it in GitHub Desktop.
Applicative Blog
{-# LANGUAGE GADTs #-}
import Control.Applicative.Free
import Control.Applicative
type Author = String
type Post = String
type Id = Int
-- A page of the blog, that will consist of a post and its author
data Page = Page {
post :: Post,
author :: Author
} deriving Show
-- Our ADT
data BlogF a where
GetPost :: Id -> BlogF Post
GetAuthor :: Id -> BlogF Author
-- Our Free Applicative
type Blog a = Ap BlogF a
-- Convenience functions
getPost :: Id -> Blog Post
getPost id = liftAp $ GetPost id
getAuthor :: Id -> Blog Author
getAuthor id = liftAp $ GetAuthor id
-- as you can imagine, a Page does not need for the post and author to be
-- fetched in certain order, it's applicative!
renderPage :: Id -> Id -> Blog Page
renderPage postId authorId = Page <$> getPost postId
<*> getAuthor authorId
-- The interpreter for our Free Applicative. Theoretically is a Natural
-- transformation with the shape (BlogF ~> IO)
interpIO :: BlogF a -> IO a
interpIO (GetPost id) = putStrLn ("getting post " ++ show id ++ " from DB") *> pure "this is the post"
interpIO (GetAuthor id) = putStrLn ("getting author " ++ show id ++ " from DB") *> pure "Pepe García"
main :: IO ()
main = do
page <- runAp interpIO $ renderPage 1 1
print page
@pepegar
Copy link
Author

pepegar commented Sep 14, 2016

The output of the program is:

getting post 1 from DB
getting author 1 from DB
Page {post = "this is the post", author = "Pepe Garc\237a"}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment