Skip to content

Instantly share code, notes, and snippets.

@myuon
Created December 31, 2013 11:43
Show Gist options
  • Save myuon/8195637 to your computer and use it in GitHub Desktop.
Save myuon/8195637 to your computer and use it in GitHub Desktop.
extensible-effectsのReader, Writer, Stateを試してみる ref: http://qiita.com/myuon_myon/items/a172ed5d765b4385d974
{-# LANGUAGE FlexibleContexts, DeriveDataTypeable #-}
import Control.Eff
import Control.Eff.Reader.Lazy
import Control.Eff.State.Lazy
import Control.Eff.Writer.Lazy
import Data.Typeable (Typeable)
import Control.Monad
type Task = String
newtype Worker = Worker { todo :: [Task] }
deriving (Eq, Show, Typeable)
-- State版
resetTodo :: (Member (State Worker) r) => Eff r ()
resetTodo = put $ Worker ["EOF"]
-- Reader版
nextTask :: (Member (Reader Worker) r) => Eff r Task
nextTask = do
Worker u <- ask
return $ head u
-- State版
nextTask' :: (Member (State Worker) r) => Eff r Task
nextTask' = do
Worker u <- get
return $ head u
-- ここではクロージャーっぽいことをしている
updateHead :: (Member (State Worker) r) => (Task -> Task) -> Eff r ()
updateHead f = do
Worker ts <- get
put $ Worker $ go f ts
where
go :: (s -> s) -> [s] -> [s]
go _ [] = []
go f (a:as) = f a:as
example1 = do
let w = Worker ["todo1", "todo2", "todo3", "EOF"]
putStrLn $ run $ runReader nextTask w
-- output: todo1
print $ run $ runState w nextTask'
-- output: (Worker {todo = ["todo1","todo2","todo3","EOF"]},"todo1")
putStrLn $ run $ evalState w nextTask'
-- output: todo1
print $ run $ runState w resetTodo
-- output: (Worker {todo = ["EOF"]},())
putStrLn $ run . runReader nextTask
$ run . execState w
$ updateHead (++ ": 1st task")
-- output: todo1: 1st task
-- Taskを1つだけ処理する
doTask :: (Member (Writer String) r, Member (State Worker) r) => Eff r ()
doTask = do
Worker ts <- get
when (length ts >= 2) $ do
put $ Worker $ tail ts
tell $ "task was done -> " ++ (head ts) ++ ".\n"
-- Taskを全て処理する
doTaskAll :: (Member (Writer String) r, Member (State Worker) r) => Eff r ()
doTaskAll = do
doTask
Worker ts <- get
when (length ts >= 2) $ doTaskAll
example2 = do
let w = Worker ["todo1", "todo2", "todo3", "EOF"]
print $ run $ runWriter (++) "" $ execState w doTask
-- output: ("task was done -> todo1.\n",Worker {todo = ["todo2","todo3","EOF"]})
print $ run $ runWriter (++) "" $ execState w doTaskAll
-- output: ("task was done -> todo1.\ntask was done -> todo2.\ntask was done -> todo3.\n",Worker {todo = ["EOF"]})
print $ run $ execState w $ runWriter (++) "" $ doTaskAll
-- output: Worker {todo = ["EOF"]}
main = do
example1
example2
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment