Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/samuelschlesinger/mtl-uplift
A way to lift entire substacks of monad transformer stacks, boilerplate free!
https://github.com/samuelschlesinger/mtl-uplift
Last synced: 20 days ago
JSON representation
A way to lift entire substacks of monad transformer stacks, boilerplate free!
- Host: GitHub
- URL: https://github.com/samuelschlesinger/mtl-uplift
- Owner: SamuelSchlesinger
- License: mit
- Created: 2020-09-27T20:06:07.000Z (over 4 years ago)
- Default Branch: master
- Last Pushed: 2020-09-27T20:46:07.000Z (over 4 years ago)
- Last Synced: 2024-11-27T19:44:54.878Z (about 1 month ago)
- Language: Haskell
- Size: 6.84 KB
- Stars: 1
- Watchers: 3
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# mtl-uplift
[![Hackage](https://img.shields.io/hackage/v/mtl-uplift.svg)](https://hackage.haskell.org/package/mtl-uplift)
Uplift entire substacks of monad transformer stacks, boilerplate free!
Many industry Haskell programmers are all too familiar with code like:
```haskell
lift . lift . lift . lift . lift . lift . lift . lift . lift . lift . lift . lift . lift $ do
blah
```
This may or may not be an exaggeration. Now, we can just write the much less
visually annoying:
```haskell
uplift @TopOfSubstackT $ do
blah
```
This relieves the programmer from having to do any bookkeeping about what
level of their greater stack their substack lives at, but just to know which monad tops it.
Beyond that, if we transform our stack, with the old code we would potentially have to modify the number of
calls to `lift`, but now, as long as we still want to `uplift` a substack with
the same top, we don't have to. Isn't that uplifting?Here is a more complete example from the tests:
```haskell
{-# LANGUAGE TypeApplications #-}
{-# LANGUAGE BlockArguments #-}
module Main whereimport Control.Monad.Trans.Uplift
import Control.Monad.State
import Control.Monad.Writer
import Control.Monad.Readertype Stack = StateT Bool (WriterT [String] (ReaderT Char IO))
runStack :: Stack a -> IO (a, [String])
runStack stack = runReaderT (runWriterT (evalStateT stack True)) 'X'main :: IO ()
main = do
(a, xs) <- runStack do
uplift @(WriterT [String]) do
tell ["One", "Two"]
c <- uplift @(ReaderT Char) ask
if c == 'X' then tell ["One, Two, Three, Four"]
else pure ()
guard (xs == ["One", "Two", "One, Two, Three, Four"])
```