0 | module Control.Monad.JustAMonad
11 | import Language.Reflection
13 | import System.File.ReadWrite
15 | import Text.PrettyPrint.Prettyprinter.Render.Terminal
16 | import Text.PrettyPrint.Prettyprinter
18 | import public System.Clock
20 | %language ElabReflection
24 | Arrow : Type -> Type -> Type
28 | data Channel = Timing | Debug
32 | channelShow : Show Channel
33 | channelShow = %runElab derive
37 | Timing == Timing = True
38 | Debug == Debug = True
43 | Subset : Type -> Type
44 | Subset a = a -> Bool
49 | M : (err : Type) -> (st : Type) -> (res : Type) -> Type
50 | M e s = Arrow (Subset Channel, s) . IO . (Subset Channel,) . Either e . (s,)
56 | (>>=) : M e s a -> (a -> M e s b) -> M e s b
57 | m >>= f = \s => Prelude.do
59 | (ch, Left e) => pure (ch, Left e)
60 | (ch, Right (s, x)) => f x (ch, s)
64 | (=<<) : (a -> M e s b) -> M e s a -> M e s b
70 | (>=>) : (a -> M e s b) -> (b -> M e s c) -> (a -> M e s c)
71 | (>=>) f g x = g !(f x)
75 | (<=<) : (b -> M e s c) -> (a -> M e s b) -> (a -> M e s c)
80 | (>>) : M e s () -> M e s b -> M e s b
81 | (>>) m f = (>>=) m (const f)
86 | return : a -> M e s a
87 | return x = \(ch, s) => pure (ch, Right (s, x))
92 | throw : e -> M e s a
93 | throw e (ch, s) = pure (ch, Left e)
99 | get = \(ch, s) => pure (ch, Right (s, s))
104 | set : s -> M e s ()
105 | set s (ch, _) = pure (ch, Right (s, ()))
110 | update : (s -> s) -> M e s ()
111 | update f = get >>= set . f
114 | mapError : (e -> e') -> M e s a -> M e' s a
115 | mapError f m = \s => Prelude.do
117 | (ch, Left x) => pure (ch, Left (f x))
118 | (ch, Right x) => pure (ch, Right x)
121 | mapState : (s -> s') -> (s' -> s) -> M e s a -> M e s' a
122 | mapState f f' m = \(ch, s') => Prelude.do
123 | case !(m (ch, f' s')) of
124 | (ch, Left x) => pure (ch, Left x)
125 | (ch, Right (st, x)) => pure (ch, Right (f st, x))
128 | mapResult : (a -> b) -> M e s a -> M e s b
129 | mapResult f m = \s => Prelude.do
131 | (ch, Left x) => pure (ch, Left x)
132 | (ch, Right (st, x)) => pure (ch, Right (st, f x))
135 | (<$>) : (a -> b) -> M e s a -> M e s b
139 | (<&>) : M e s a -> (a -> b) -> M e s b
140 | (<&>) = flip mapResult
143 | (<*>) : M e s (a -> b) -> M e s a -> M e s b
150 | fromEither : Either e a -> M e s a
151 | fromEither (Left x) (ch, s) = pure (ch, Left x)
152 | fromEither (Right x) (ch, s) = pure (ch, Right (s, x))
156 | run : M e s r -> s -> IO (Either e (s, r))
157 | run m initial = map snd (m (const True, initial))
161 | eval : M e s r -> s -> IO (Either e r)
162 | eval m initial = Prelude.do
163 | case !(m (const True, initial)) of
164 | (ch, Left x) => pure (Left x)
165 | (ch, Right (st, x)) => pure (Right x)
169 | discard : M e s a -> M e s ()
170 | discard x = x >>= const (return ())
174 | when : Bool -> M e s () -> M e s ()
176 | when False x = return ()
180 | isListening : Channel -> M e s Bool
181 | isListening me = \(listen, s) => pure (listen, (Right (s, listen me)))
185 | doListen : Channel -> Bool -> M e s ()
186 | doListen ch switch = \(listen, s) => pure (set listen ch switch, Right (s, ()))
188 | set : (Channel -> Bool) -> Channel -> Bool -> Channel -> Bool
195 | sequenceMaybe : Maybe (M e s a) -> M e s (Maybe a)
196 | sequenceMaybe Nothing = return Nothing
197 | sequenceMaybe (Just x) = return (Just !x)
200 | sequenceList : List (M e s a)
202 | sequenceList [] = return []
203 | sequenceList (x :: xs) = return (!x :: !(sequenceList xs))
206 | sequenceVect : Vect n (M e s a)
207 | -> M e s (Vect n a)
208 | sequenceVect [] = return []
209 | sequenceVect (x :: xs) = return (!x :: !(sequenceVect xs))
212 | sequenceSnocList : SnocList (M e s a)
213 | -> M e s (SnocList a)
214 | sequenceSnocList [<] = return [<]
215 | sequenceSnocList (xs :< x) = return (!(sequenceSnocList xs) :< !x)
218 | sequenceList1 : List1 (M e s a)
220 | sequenceList1 (x ::: []) = return (singleton !x)
221 | sequenceList1 (x ::: y :: zs) = return (!x `cons` !(sequenceList1 (y ::: zs)))
224 | sequenceProduct : (M e s a, M e s b)
226 | sequenceProduct (f, g) = return (!f, !g)
229 | sequenceEither : Either (M e s a) (M e s b)
230 | -> M e s (Either a b)
231 | sequenceEither (Left f) = return (Left !f)
232 | sequenceEither (Right g) = return (Right !g)
236 | forList : List a -> (a -> M e s b) -> M e s (List b)
237 | forList xs f = sequenceList (map f xs)
241 | forProduct : (a, b)
245 | forProduct p f g = sequenceProduct (bimap f g p)
248 | traverseProduct : (a -> M e s a')
252 | traverseProduct f g p = forProduct p f g
255 | forCatMaybes : List a
256 | -> (a -> M e s (Maybe b))
258 | forCatMaybes list f =
259 | mapResult catMaybes (forList list f)
263 | forList1 : List1 a -> (a -> M e s b) -> M e s (List1 b)
264 | forList1 xs f = sequenceList1 (map f xs)
268 | forSnocList : SnocList a -> (a -> M e s b) -> M e s (SnocList b)
269 | forSnocList xs f = sequenceSnocList (map f xs)
272 | traverseSnocList : (a -> M e s b)
274 | -> M e s (SnocList b)
275 | traverseSnocList f xs = forSnocList xs f
278 | traverseList : (a -> M e s b)
281 | traverseList f xs = forList xs f
284 | traverseList1 : (a -> M e s b)
287 | traverseList1 f xs = forList1 xs f
290 | traverseList_ : (a -> M e s ())
293 | traverseList_ f xs = discard $
traverseList f xs
296 | traverseList1_ : (a -> M e s ())
299 | traverseList1_ f xs = discard $
traverseList1 f xs
303 | forVect : Vect n a -> (a -> M e s b) -> M e s (Vect n b)
304 | forVect xs f = sequenceVect (map f xs)
308 | forMaybe : Maybe a -> (a -> M e s b) -> M e s (Maybe b)
309 | forMaybe mb f = sequenceMaybe (map f mb)
312 | traverseMaybe : (a -> M e s b)
315 | traverseMaybe f m = forMaybe m f
318 | forList_ : List a -> (a -> M e s b) -> M e s ()
319 | forList_ xs f = discard $
forList xs f
322 | forSnocList_ : SnocList a -> (a -> M e s b) -> M e s ()
323 | forSnocList_ xs f = discard $
forSnocList xs f
326 | forVect_ : Vect n a -> (a -> M e s b) -> M e s ()
327 | forVect_ xs f = discard $
forVect xs f
330 | filterMaybeListM : List a -> (a -> M e s (Maybe b)) -> M e s (List b)
331 | filterMaybeListM [] f = return []
332 | filterMaybeListM (x :: xs) f = M.do
333 | rest <- filterMaybeListM xs f
336 | Nothing => return rest
337 | Just x' => return (x' :: rest)
341 | try : M e s a -> M e s (Either e a)
342 | try m = \(ch, s) => Prelude.do
343 | case !(m (ch, s)) of
344 | (ch, Left x) => pure (ch, Right (s, Left x))
345 | (ch, Right (s, x)) => pure (ch, Right (s, Right x))
349 | one : M e s a -> M e s b -> M e s (Either a b)
352 | Right x => return (Left x)
353 | Left _ => g <&> Right
357 | both : M e s a -> M e s b -> M e s (a, b)
358 | both f g = (f <&> (,)) <*> g
362 | (<|>) : M e s a -> M e s a -> M e s a
363 | (f <|> g) = one f g <&> fromEither
366 | allList : List (M e s Bool) -> M e s Bool
367 | allList [] = return True
368 | allList (x :: xs) = M.do
371 | False => return False
376 | or : M e s Bool -> M e s Bool -> M e s Bool
379 | True => return True
388 | and : M e s Bool -> M e s Bool -> M e s Bool
392 | False => return False
395 | io : IO a -> M e s a
396 | io cmd (ch, s) = Prelude.do
398 | pure (ch, Right (s, r))
401 | data OutputMode = STDOUT | FILE String
405 | print_ : Channel -> OutputMode -> String -> M e s ()
406 | print_ ch mode str = M.do
407 | when !(isListening ch) $ M.do
409 | STDOUT => io $
putStrLn str
410 | FILE file => discard $
io $
appendFile {io = IO} file str
413 | timestamp : M e s (Clock Process)
414 | timestamp = io $
clockTime Process
417 | gcTimestamp : FromString e => M e s (Clock GCCPU)
419 | Just x <- io $
clockTime GCCPU
420 | | _ => throw ("GC CPU-time not supported")
425 | formatted : Clock type -> String
426 | formatted (MkClock sec nan) =
427 | let mantisa = cast {to = Int} (cast {to = Double} nan / 1_000_000) in
428 | "\{show sec}.\{pad mantisa}s"
430 | pad : Int -> String
433 | True => "00" ++ show x
436 | True => "0" ++ show x
441 | clock : FromString e => String -> M e s a -> M e s a
448 | let dif = timeDifference t1 t0
449 | let dif' = timeDifference t1' t0'
450 | print_ Timing STDOUT "\{msg} took overall-time: \{formatted dif}; gc time: \{formatted dif'}"
455 | clockWhen : FromString e => Bool -> String -> M e s a -> M e s a
456 | clockWhen False msg m = m
457 | clockWhen True msg m = clock msg m
460 | clockThresholdD : FromString e => (a -> M e s String) -> Integer -> M e s a -> M e s a
461 | clockThresholdD msg threshold m = M.do
467 | let dif = timeDifference t1 t0
468 | let dif' = timeDifference t1' t0'
469 | let workloadTime = toNano dif - toNano dif'
474 | when (workloadTime > threshold && toNano dif' > 0) $ M.do
476 | print_ Timing STDOUT "\{msg} took overall-time: \{formatted dif}; gc time: \{formatted dif'}"
481 | clockThreshold : FromString e => String -> Integer -> M e s a -> M e s a
482 | clockThreshold msg threshold m = M.do
483 | clockThresholdD (\x => return msg) threshold m
488 | write : String -> M e s ()
490 | print_ Debug STDOUT x
494 | time : FromString e => M e s a -> M e s (a, Clock Duration)
495 | time computation = M.do
501 | let dif = timeDifference t1 t0
502 | let dif' = timeDifference t1' t0'
503 | let workloadTime = timeDifference dif dif'
504 | return (x, workloadTime)