never executed always true always false
1 module HelVM.HelMA.Automaton.Trampoline where
2
3 import Control.Monad.Loops
4 import Control.Type.Operator
5
6 import Prelude hiding ( break )
7
8 testMaybeLimit ∷ LimitMaybe
9 testMaybeLimit = Just $ fromIntegral (maxBound :: Int)
10
11 trampolineMWithLimit ∷ Monad m ⇒ (a → m $ Same a) → LimitMaybe → a → m a
12 trampolineMWithLimit f Nothing x = trampolineM f x
13 trampolineMWithLimit f (Just n) x = trampolineM (actMWithLimit f) (n , x)
14
15 actMWithLimit ∷ Monad m ⇒ (a → m $ Same a) → WithLimit a → m $ EitherWithLimit a
16 actMWithLimit f (n , x) = checkN n where
17 checkN 0 = pure $ break x
18 checkN _ = next n <$> f x
19
20 next ∷ Natural → Same a → EitherWithLimit a
21 next n a = withLimit n <$> a
22
23 withLimit ∷ Natural → a → WithLimit a
24 withLimit n a = (n - 1 , a)
25
26 trampolineM ∷ Monad m ⇒ (a → m (Either b a)) → a → m b
27 trampolineM f = fmap (fromLeft $ error "unreachable") . iterateUntilM isLeft (either (pure . Left) f) . Right
28
29 trampoline ∷ (a → Either b a) → a → b
30 trampoline f = fromLeft (error "unreachable") . iterateUntil isLeft (either Left f) . Right
31
32 continue ∷ a → Either b a
33 continue = Right
34
35 break ∷ b → Either b a
36 break = Left
37
38 type LimitMaybe = Maybe Natural
39
40 type EitherWithLimit a = Either a $ WithLimit a
41
42 type WithLimit a = (Natural , a)
43
44 type Same a = Either a a