Add MonadUnlift
This commit is contained in:
parent
e0872b4d45
commit
878af237f4
94
src/Control/Monad/Unlift.purs
Normal file
94
src/Control/Monad/Unlift.purs
Normal file
@ -0,0 +1,94 @@
|
|||||||
|
module Control.Monad.Unlift where
|
||||||
|
|
||||||
|
import Prelude
|
||||||
|
|
||||||
|
import Control.Monad.Base (class MonadBase)
|
||||||
|
import Control.Monad.Identity.Trans (IdentityT(..))
|
||||||
|
import Control.Monad.Reader (ReaderT(..))
|
||||||
|
import Control.Monad.ST (ST)
|
||||||
|
import Data.Either (Either)
|
||||||
|
import Data.Identity (Identity)
|
||||||
|
import Data.List (List)
|
||||||
|
import Data.List.Lazy as LL
|
||||||
|
import Data.Maybe (Maybe)
|
||||||
|
import Effect (Effect)
|
||||||
|
import Effect.Aff (Aff)
|
||||||
|
|
||||||
|
-- | Monads which allow their actions to be run in their base monad.
|
||||||
|
-- |
|
||||||
|
-- | `MonadUnlift` captures the opposite notion of `MonadBase` - while
|
||||||
|
-- | `MonadBase` allows an base monad `b` to be lifted into another monad `m`,
|
||||||
|
-- | `MonadUnlift` allows a `m` to be run in `b`, as long as contained in an
|
||||||
|
-- | outer `m` context.
|
||||||
|
-- |
|
||||||
|
-- | Note that the laws given below require that a monad have no "monadic
|
||||||
|
-- | state", which essentially limits instances to `ReaderT` and `IdentityT`
|
||||||
|
-- | stacks with a base of `b`.
|
||||||
|
-- |
|
||||||
|
-- | Instances should satisfy the following laws, which state that
|
||||||
|
-- | `unlift` is a transformer of monads for any given `u` returned by
|
||||||
|
-- | `askUnlift`:
|
||||||
|
-- |
|
||||||
|
-- | ```purescript
|
||||||
|
-- | unlift u <<< pure = pure
|
||||||
|
-- | unlift u (f =<< m) = unlift u <<< f =<< unlift u m
|
||||||
|
-- | ```
|
||||||
|
class MonadBase b m <= MonadUnlift b m | m -> b where
|
||||||
|
-- | Run a base monad action with access to a runner function that is capable
|
||||||
|
-- | of running a monadic action `m` in `b` (strictly speaking, a natural
|
||||||
|
-- | transformation from `m` to `b`).
|
||||||
|
withRunInBase :: forall x. ((m ~> b) -> b x) -> m x
|
||||||
|
|
||||||
|
instance MonadUnlift Array Array where
|
||||||
|
withRunInBase runAction = runAction identity
|
||||||
|
|
||||||
|
instance MonadUnlift List List where
|
||||||
|
withRunInBase runAction = runAction identity
|
||||||
|
|
||||||
|
instance MonadUnlift LL.List LL.List where
|
||||||
|
withRunInBase runAction = runAction identity
|
||||||
|
|
||||||
|
instance MonadUnlift Maybe Maybe where
|
||||||
|
withRunInBase runAction = runAction identity
|
||||||
|
|
||||||
|
instance MonadUnlift Effect Effect where
|
||||||
|
withRunInBase runAction = runAction identity
|
||||||
|
|
||||||
|
instance MonadUnlift Aff Aff where
|
||||||
|
withRunInBase runAction = runAction identity
|
||||||
|
|
||||||
|
instance MonadUnlift Identity Identity where
|
||||||
|
withRunInBase runAction = runAction identity
|
||||||
|
|
||||||
|
instance MonadUnlift (Either e) (Either e) where
|
||||||
|
withRunInBase runAction = runAction identity
|
||||||
|
|
||||||
|
instance MonadUnlift (ST s) (ST s) where
|
||||||
|
withRunInBase runAction = runAction identity
|
||||||
|
|
||||||
|
instance MonadUnlift b m => MonadUnlift b (ReaderT r m) where
|
||||||
|
withRunInBase runAction = ReaderT \context ->
|
||||||
|
withRunInBase \runMInBase ->
|
||||||
|
runAction \(ReaderT reader) ->
|
||||||
|
runMInBase $ reader context
|
||||||
|
|
||||||
|
instance MonadUnlift b m => MonadUnlift b (IdentityT m) where
|
||||||
|
withRunInBase runAction = IdentityT $
|
||||||
|
withRunInBase \runMInBase ->
|
||||||
|
runAction \(IdentityT a) ->
|
||||||
|
runMInBase a
|
||||||
|
|
||||||
|
newtype Unlift :: forall k. (k -> Type) -> (k -> Type) -> Type
|
||||||
|
newtype Unlift b m = Unlift (m ~> b)
|
||||||
|
|
||||||
|
askUnlift :: forall b m. MonadUnlift b m => m (Unlift b m)
|
||||||
|
askUnlift = withRunInBase \run -> pure $ Unlift run
|
||||||
|
|
||||||
|
askRunInBase :: forall b m a. MonadUnlift b m => m (m a -> b a)
|
||||||
|
askRunInBase = withRunInBase pure
|
||||||
|
|
||||||
|
withUnlift :: forall b m a. MonadUnlift b m => (Unlift b m -> b a) -> m a
|
||||||
|
withUnlift runAction = withRunInBase \run -> runAction $ Unlift run
|
||||||
|
|
||||||
|
toBase :: forall b m a. MonadUnlift b m => m a -> m (b a)
|
||||||
|
toBase m = withRunInBase \run -> pure $ run m
|
Loading…
Reference in New Issue
Block a user