Interruptible.hs 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100
  1. {-# LANGUAGE TypeFamilies #-}
  2. module Control.Monad.Trans.Interruptible (
  3. module Control.Monad.Trans.Interruptible.Class,
  4. -- * Interruptible applications
  5. intercalateWith,
  6. intercalateFold,
  7. intercalateAction,
  8. intercalateAction'
  9. )where
  10. import Control.Monad.Trans.Interruptible.Class
  11. import Data.Traversable
  12. import Data.Foldable
  13. {-# DEPRECATED intercalateWith "Use intercalateFold instead" #-}
  14. {- |
  15. Intercalates folding the given function in each of contexts on the traversable.
  16. The first argument is the resume function that will be used on the folds.
  17. That is:
  18. @
  19. intercalateFold resume f [b1, b2] [a00, a10, a20] = do
  20. a01 <- resume (f b1) a00
  21. a11 <- resume (f b1) a10
  22. a21 <- resume (f b1) a20
  23. a02 <- resume (f b2) a11
  24. a12 <- resume (f b2) a21
  25. a22 <- resume (f b2) a31
  26. return [a02, a12, a22]
  27. @
  28. Where the order of the operations is guaranteed.
  29. This is usefull for consuming lazy sequences.
  30. The resume function is parametric for allowing resuming deeper Interruptible chains, with
  31. resume2, resume3, etc.
  32. -}
  33. intercalateFold :: (Traversable t, Foldable f, Monad m) =>
  34. ((a -> transf a) -> transfCtx -> m (transfCtx)) ->
  35. (b -> a -> transf a) -> f b -> t transfCtx -> m (t transfCtx)
  36. intercalateFold res f bb aa = intercalateFold' res f (toList bb) aa
  37. where
  38. intercalateFold' _ _ [] aa = return aa
  39. intercalateFold' res f (b:bb) aa = do
  40. aa' <- mapM (res $ f b) aa
  41. intercalateFold' res f bb aa'
  42. -- | Exactly the same as intercalateFold, for backwards compatibility.
  43. intercalateWith :: (Traversable t, Foldable f, Monad m) =>
  44. ((a -> transf a) -> transfCtx -> m (transfCtx)) ->
  45. (b -> a -> transf a) -> f b -> t transfCtx -> m (t transfCtx)
  46. intercalateWith = intercalateFold
  47. {- |
  48. Intercalates the execution of the function, on the interrupted contexts given, but instead of
  49. folding them over a list like "intercalateWith", it folds them on the result of the monadic
  50. action untill it returns Nothing.
  51. That is, if @get@ is a monadic action that when repeated called returns @Just "a"@, @Just "b"@,
  52. @Just "c"@ and @Nothing@, those two lines are equivalent:
  53. > intercalateFold resume f ["a", "b", "c"] ctxs
  54. > intercalateAction resume f get ctxs
  55. IntercalateAction can intercalate contexts over non-lazy IO.
  56. -}
  57. intercalateAction :: (Traversable t, Monad m) =>
  58. ((a -> transf a) -> transfCtx -> m (transfCtx)) ->
  59. (b -> a -> transf a) -> m (Maybe b) -> t transfCtx -> m (t transfCtx)
  60. intercalateAction res f get ctx = do
  61. v' <- get
  62. case v' of
  63. Nothing -> return ctx
  64. Just v -> mapM (res $ f v) ctx >>= intercalateAction res f get
  65. {- |
  66. Behaves like intercalateAction, but the action will update a parameter.
  67. Those are equivalent:
  68. > intercalateAction resume f get ctxs
  69. > get' x = (\v -> (v, x)) <$> get
  70. > fst <$> intercalateAction' resume f () get' ctxs
  71. -}
  72. intercalateAction' :: (Traversable t, Monad m) =>
  73. ((a -> transf a) -> transfCtx -> m (transfCtx)) ->
  74. (b -> a -> transf a) -> (p -> m (Maybe b, p)) -> (t transfCtx, p) -> m (t transfCtx, p)
  75. intercalateAction' res f get (ctx, p) = do
  76. (v', p') <- get p
  77. case v' of
  78. Nothing -> return (ctx, p)
  79. Just v -> do
  80. ctx' <- mapM (res $ f v) ctx
  81. intercalateAction' res f get (ctx', p')