Created
August 3, 2015 01:05
-
-
Save levinotik/5c5e1ee2554972a5cb74 to your computer and use it in GitHub Desktop.
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
module TransformersPart1 where | |
import Control.Monad.Trans.Maybe | |
import Data.Functor | |
import Text.Read (readMaybe) | |
-- plain old Maybe example (avoiding division by zero) | |
ex1 :: Int -> Int -> Maybe Int | |
ex1 x y | y > 0 = Just (x `div` y) | |
| otherwise = Nothing | |
-- now we have two Monad layers. Maybe and IO. | |
ex2 :: IO (Maybe Int) | |
ex2 = readMaybe <$> getLine | |
-- using the previous example, we now want to map the Int to a String | |
-- we fmap twice; once on the IO and then on the Maybe. | |
ex3 :: IO (Maybe String) | |
ex3 = fmap (fmap show) ex2 | |
-- we can actually do this for any two functors though | |
-- because functors compose | |
ex4 :: (Functor f, Functor g) => (a -> b) -> f (g a) -> f (g b) | |
ex4 f a = fmap (fmap f) a | |
-- but when we try to bind we have issues | |
-- we can do it if we know about one of the Monads. | |
ex5 :: Monad m => m (Maybe a) -> (a -> m (Maybe b)) -> m (Maybe b) | |
ex5 a f = a >>= (maybe (return Nothing) f) | |
-- but you can't write bind for any two arbitrary monads | |
ex6 :: (Monad m, Monad n) => m (n a) -> (a -> m (n b)) -> m (n b) | |
ex6 = error "try implementing it" | |
-- With transformers, you have a monad instance for the transformer | |
-- where there's a concrete monad and any other monad on top. Hence | |
-- Monad transformers such as MaybeT, EitherT, etc. The monad instance has to | |
-- be defined with regard to some known, conrete monad + an arbitrary monad. | |
-- the type is `newtype MaybeT m a` so we can use `ex2` to construct one | |
ex7 :: MaybeT IO Int | |
ex7 = MaybeT $ ex2 | |
-- the monad instance for MaybeT lets us to a single bind | |
ex8 :: MaybeT IO Int | |
ex8 = do | |
x <- ex7 | |
return (x + 1) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment