0 | module Interactive.FS
2 | import Data.Container
3 | import Data.Container.Morphism
4 | import Data.Container.Kleene
12 | data OpenFile = MkOpen String
13 | data WriteFile = MkWrite String File
14 | data CloseFile = MkClose File
17 | FSMonad : Type -> Type
18 | FSMonad = IO . Either FileError
20 | Functor FSMonad where
23 | Applicative FSMonad where
25 | x <*> y = do x' <- x
30 | x >>= f = do x' <- x
35 | OpenC = OpenFile :- File
38 | WriteC = WriteFile :- Unit
41 | CloseC = CloseFile :- Unit
45 | FileAPI = OpenC + WriteC + CloseC
47 | writeMany : F FSMonad (WriteC).º =%> CUnit
48 | writeMany = embed writeFS
50 | writeFS : (x : StarShp WriteC) -> FSMonad (StarPos WriteC x)
51 | writeFS Done = pure (pure StarU)
52 | writeFS (More ((MkWrite content file) ## p2)) = do
53 | putStrLn "writing `\{content}` to file"
54 | Right () <- fPutStrLn {io = IO} file content
55 | | Left err => putStrLn "error \{show err}" *> pure (Left err)
56 | map (map (StarM ())) (writeFS (p2 ()))
60 | FileSession : Container
61 | FileSession = OpenC ○ (WriteC).º ○ CloseC
63 | testWrite : F FSMonad WriteC =%> CUnit
64 | testWrite = embed (\(MkWrite content fh) => fPutStr fh content)
66 | testOpen : F FSMonad OpenC =%> CUnit
67 | testOpen = embed (\(MkOpen filename) => openFile filename ReadWrite)
69 | testClose : F FSMonad CloseC =%> CUnit
70 | testClose = embed (\(MkClose fh) => map pure (closeFile fh))
72 | testFS : F FSMonad FileAPI =%> CUnit
73 | testFS = distrib_plus_3 {a = OpenC, b = WriteC, c = CloseC, f = FSMonad}
74 | |> (testOpen + testWrite + testClose |> dia3)
77 | writeHello : (FileSession).req
78 | writeHello = ((MkOpen "append"
79 | ## (\file => single (MkWrite "hello" file)))
80 | ## (\val => MkClose val.π1))
82 | runSession : (FileSession).req -> IO Unit
84 | = let rr := runSequenceM3 p1 testOpen writeMany testClose
85 | {a = OpenC, b = (WriteC).º, c = CloseC, m = FSMonad}
89 | main = runSession writeHello