1
{-# LANGUAGE TupleSections #-}
2
3
module Agda.Utils.Function where
5
-- | Repeat something while a condition on some state is true.
6
-- Return the last state (including the changes of the last
7
-- transition, even if the condition became false then).
9
repeatWhile :: (a -> (Bool, a)) -> a -> a
10
repeatWhile f = loop where
11
loop a = if again then loop a' else a'
12
where (again, a') = f a
14
-- | Monadic version of 'repeatWhile'.
15
repeatWhileM :: (Monad m) => (a -> m (Bool, a)) -> a -> m a
16
repeatWhileM f = loop where
19
if again then loop a' else return a'
4
21
-- | A version of the trampoline function.
6
23
-- The usual function iterates @f :: a -> Maybe a@ as long
7
24
-- as @Just{}@ is returned, and returns the last value of @a@
10
trampoline :: (a -> (Bool, a)) -> a -> a
27
-- @usualTrampoline f = trampolineWhile $ \ a -> maybe (False,a) (True,) (f a)@.
29
-- @trampolineWhile@ is very similar to @repeatWhile@, only that
30
-- it discards the state on which the condition went @False@,
31
-- and returns the last state on which the condition was @True@.
32
trampolineWhile :: (a -> (Bool, a)) -> a -> a
33
trampolineWhile f = repeatWhile $ \ a ->
35
in (again,) $ if again then a' else a
37
-- | Monadic version of 'trampolineWhile'.
38
trampolineWhileM :: (Monad m) => (a -> m (Bool, a)) -> a -> m a
39
trampolineWhileM f = repeatWhileM $ \ a -> do
41
return $ (again,) $ if again then a' else a
43
-- | More general trampoline, which allows some final computation
44
-- from iteration state @a@ into result type @b@.
45
trampoline :: (a -> Either b a) -> a -> b
11
46
trampoline f = loop where
12
loop a = if again then loop a' else a'
13
where (again, a') = f a
47
loop a = either id loop $ f a
15
49
-- | Monadic version of 'trampoline'.
16
trampolineM :: (Monad m) => (a -> m (Bool, a)) -> a -> m a
50
trampolineM :: Monad m => (a -> m (Either b a)) -> a -> m b
17
51
trampolineM f = loop where
20
if again then loop a' else return a'
52
loop a = either return loop =<< f a
22
54
-- | Iteration to fixed-point.
65
96
-- | @applyUnless b f a@ applies @f@ to @a@ unless @b@.
66
97
applyUnless :: Bool -> (a -> a) -> a -> a
67
98
applyUnless b f = if b then id else f
100
-- | Monadic version of @applyWhen@
101
applyWhenM :: (Monad m) => m Bool -> (m a -> m a) -> m a -> m a
102
applyWhenM mb f x = mb >>= \ b -> applyWhen b f x
104
-- | Monadic version of @applyUnless@
105
applyUnlessM :: (Monad m) => m Bool -> (m a -> m a) -> m a -> m a
106
applyUnlessM mb f x = mb >>= \ b -> applyUnless b f x