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