21 | data RIO : (x : Type) -> (a : Type) -> Type where
22 | Lift : (run : PrimIO (Either x a)) -> RIO x a
23 | Chain : RIO x1 a -> (Either x1 a -> RIO x2 b) -> RIO x2 b
26 | data Stack : (x1,x2,a,b : Type) -> Type where
28 | (::) : (Either x1 a -> RIO y v) -> Stack y x2 v b -> Stack x1 x2 a b
32 | eval : RIO x a -> IO (Either x a)
33 | eval app = fromPrim $
go app []
36 | go : RIO x1 v -> Stack x1 x2 v w -> PrimIO (Either x2 w)
37 | go (Chain z f) st w = go z (f :: st) w
38 | go (Lift run) [] w = run w
39 | go (Lift run) (f :: fs) w =
40 | let MkIORes ei w2 = run w
41 | in assert_total $
go (f ei) fs w2
46 | run : Uninhabited x => RIO x a -> IO a
47 | run app = either absurd id <$> eval app
51 | liftEither : Either x a -> RIO x a
52 | liftEither v = Lift $
\w => MkIORes v w
56 | liftEitherIO : IO (Either x a) -> RIO x a
57 | liftEitherIO io = Lift $
toPrim io
61 | mapApp : (Either x a -> Either y b) -> RIO x a -> RIO y b
62 | mapApp f app = Chain app (liftEither . f)
67 | fail err = liftEither (Left err)
70 | bindApp : RIO x a -> (a -> RIO x b) -> RIO x b
71 | bindApp app f = Chain app (either fail f)
74 | Functor (RIO x) where
79 | bimap f g = mapApp (bimap f g)
82 | Applicative (RIO x) where
83 | pure v = liftEither (Right v)
84 | af <*> aa = bindApp af (\f => map f aa)
92 | liftIO io = Lift $
toPrim (map Right io)
96 | catch : (x -> RIO y a) -> RIO x a -> RIO y a
97 | catch f app = Chain app (either f pure)
102 | finally : RIO x () -> RIO x a -> RIO x a
103 | finally cleanup app =
104 | Chain app (either (\e => cleanup >> fail e) (\v => cleanup $> v))
107 | lift : Uninhabited x => RIO x a -> RIO y a
108 | lift io = catch (\v => absurd v) io