idris-0.9.8: effects/Effect/StdIO.idr
module Effect.StdIO
import Effects
import Control.IOExcept
data StdIO : Effect where
PutStr : String -> StdIO () () ()
GetStr : StdIO () () String
instance Handler StdIO IO where
handle () (PutStr s) k = do putStr s; k () ()
handle () GetStr k = do x <- getLine; k () x
instance Handler StdIO (IOExcept a) where
handle () (PutStr s) k = do ioe_lift (putStr s); k () ()
handle () GetStr k = do x <- ioe_lift getLine; k () x
-- Handle effects in a pure way, for simulating IO for unit testing/proof
data IOStream a = MkStream (List String -> (a, List String))
instance Handler StdIO IOStream where
handle () (PutStr s) k
= MkStream (\x => case k () () of
MkStream f => let (res, str) = f x in
(res, s :: str))
handle {a} () GetStr k
= MkStream (\x => case x of
[] => cont "" []
(t :: ts) => cont t ts)
where
cont : String -> List String -> (a, List String)
cont t ts = case k () t of
MkStream f => f ts
--- The Effect and associated functions
STDIO : EFFECT
STDIO = MkEff () StdIO
putStr : Handler StdIO e => String -> Eff e [STDIO] ()
putStr s = PutStr s
putStrLn : Handler StdIO e => String -> Eff e [STDIO] ()
putStrLn s = putStr (s ++ "\n")
getStr : Handler StdIO e => Eff e [STDIO] String
getStr = GetStr
mkStrFn : Env IOStream xs ->
Eff IOStream xs a ->
List String -> (a, List String)
mkStrFn {a} env p input = case mkStrFn' of
MkStream f => f input
where injStream : a -> IOStream a
injStream v = MkStream (\x => (v, []))
mkStrFn' : IOStream a
mkStrFn' = runWith injStream env p