-
Notifications
You must be signed in to change notification settings - Fork 37
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add UrT, the unrestricted monad transformer (#304)
Co-authored-by: Facundo Domínguez <[email protected]> Co-authored-by: Utku Demir <[email protected]>
- Loading branch information
1 parent
a12190d
commit 2c4f995
Showing
3 changed files
with
54 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
{-# LANGUAGE LinearTypes #-} | ||
-- | `UrT` creates non-linear monads from linear monads. | ||
-- The effect of @UrT m@ is the same as the effect of @m@ with the same linearity. | ||
-- It's just that the @a@ in @m a@ must be used linearly, but the @a@ in @UrT m a@ can be used unrestricted. | ||
-- Since @UrT@ is a regular monad it can be used with the regular do-notation. | ||
-- | ||
-- A good use case is when you have a linear resource, then you can use @UrT (`Linear.State` s) a@ | ||
-- to manipulate the resource linearly with regular do-notation. | ||
module Data.Unrestricted.Internal.UrT | ||
( | ||
UrT(..) | ||
, runUrT | ||
, liftUrT | ||
, evalUrT | ||
) where | ||
|
||
import qualified Control.Functor.Linear as Linear | ||
import Data.Unrestricted.Internal.Ur | ||
import Data.Unrestricted.Internal.Movable | ||
|
||
-- | @UrT@ transforms linear control monads to non-linear monads. | ||
-- | ||
-- * @UrT (`Linear.State` s) a@ is a non-linear monad with linear state. | ||
newtype UrT m a = UrT (m (Ur a)) | ||
|
||
-- | Linearly unwrap the @UrT@ newtype wrapper. | ||
runUrT :: UrT m a %1 -> m (Ur a) | ||
runUrT (UrT ma) = ma | ||
|
||
instance Linear.Functor m => Functor (UrT m) where | ||
fmap f (UrT ma) = UrT (Linear.fmap (\(Ur a) -> Ur (f a)) ma) | ||
|
||
instance Linear.Applicative m => Applicative (UrT m) where | ||
pure a = UrT (Linear.pure (Ur a)) | ||
UrT mf <*> UrT ma = UrT (Linear.liftA2 (\(Ur f) (Ur a) -> Ur (f a)) mf ma) | ||
|
||
instance Linear.Monad m => Monad (UrT m) where | ||
UrT ma >>= f = UrT (ma Linear.>>= (\(Ur a) -> case f a of (UrT mb) -> mb)) | ||
|
||
-- | Lift a computation to the @UrT@ monad, provided that the type @a@ can be used unrestricted. | ||
liftUrT :: (Movable a, Linear.Functor m) => m a %1 -> UrT m a | ||
liftUrT ma = UrT (Linear.fmap move ma) | ||
|
||
-- | Extract the inner computation linearly, the inverse of `liftUrT`. | ||
-- | ||
-- > evalUrT (liftUrT m) = m | ||
evalUrT :: Linear.Functor m => UrT m a %1 -> m a | ||
evalUrT u = Linear.fmap unur (runUrT u) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters