Interruptible.hs 1.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657
  1. {-# LANGUAGE TypeFamilies #-}
  2. module Control.Monad.Trans.Interruptible (
  3. module Control.Monad.Trans.Interruptible.Class,
  4. -- * Interruptible applications
  5. intercalateWith,
  6. intercalateAction
  7. )where
  8. import Control.Monad.Trans.Interruptible.Class
  9. {- |
  10. Folds the second list with the function applied to the first,
  11. intercalating the evaluation. That is:
  12. @
  13. intercalateWith resume f [b1, b2] [a00, a10, a20] = do
  14. a01 <- resume (f b1) a00
  15. a11 <- resume (f b1) a10
  16. a21 <- resume (f b1) a20
  17. a02 <- resume (f b2) a11
  18. a12 <- resume (f b2) a21
  19. a22 <- resume (f b2) a31
  20. return [a02, a12, a22]
  21. @
  22. Usefull for consuming lazy sequences.
  23. The resume function is parametric for allowing resuming deeper Interruptible chains, with
  24. resume2, resume3, etc.
  25. -}
  26. intercalateWith :: Monad m => ((a -> t a) -> rsta -> m (rsta)) -> (b -> a -> t a) -> [b] -> [rsta] -> m [rsta]
  27. intercalateWith _ _ [] aa = return aa
  28. intercalateWith res f (b:bb) aa = do
  29. aa' <- mapM (res $ f b) aa
  30. intercalateWith res f bb aa'
  31. {- |
  32. Intercalates the execution of the function, on the interrupted contexts given, but instead of
  33. folding them over a list like "intercalateWith", it folds them on the result of the monadic
  34. action untill it returns Nothing.
  35. That is, if @get@ is a monadic action that when repeated called returns @Just "a"@, @Just "b"@,
  36. @Just "c"@ and @Nothing@, those two lines are equivalent:
  37. > intercalateWith resume f ["a", "b", "c"] ctxs
  38. > intercalateAction resume f get ctxs
  39. IntercalateAction can intercalate contexts over non-lazy IO.
  40. -}
  41. intercalateAction :: Monad m => ((a -> t a) -> rsta -> m (rsta)) -> (b -> a -> t a) -> m (Maybe b) -> [rsta] -> m [rsta]
  42. intercalateAction res f get ctx = do
  43. v' <- get
  44. case v' of
  45. Nothing -> return ctx
  46. Just v -> mapM (res $ f v) ctx >>= intercalateAction res f get