Skip to content

Instantly share code, notes, and snippets.

@chrissound
Created December 16, 2016 15:44
Show Gist options
  • Select an option

  • Save chrissound/66aff63401f46f59ce7730843a0b59ab to your computer and use it in GitHub Desktop.

Select an option

Save chrissound/66aff63401f46f59ce7730843a0b59ab to your computer and use it in GitHub Desktop.
import Control.Monad
import Control.Monad.Trans
import Control.Applicative
data EitherMaybeT e a = EitherMaybeT {runEitherMaybe :: Either e (Maybe a)}
instance Functor (EitherMaybeT e) where
fmap f = EitherMaybeT . fmap (fmap f) . runEitherMaybe
instance Applicative (EitherMaybeT e) where
pure = return
f <*> x = EitherMaybeT $ liftA2 (<*>) (runEitherMaybe f) (runEitherMaybe x)
instance Monad (EitherMaybeT e) where
return = (\x -> EitherMaybeT $ Right (Just x))
x >>= f =
EitherMaybeT $
(case runEitherMaybe x of
Right (Just z) -> runEitherMaybe $ f z
Right (Nothing) -> Right Nothing
Left z -> Left z
)
is0 :: Int -> Maybe Int
is0 x = case x of
0 -> Nothing
x -> Just x
isMultipleOf5 :: Int -> Either String Int
isMultipleOf5 x = case mod x 5 of
0 -> Right x
_ -> Left "Value was not multiple of 5"
liftMaybe :: Maybe a -> EitherMaybeT e a
liftMaybe = EitherMaybeT . Right
liftEither :: Either e a -> EitherMaybeT e a
liftEither x = case x of
Right x' -> EitherMaybeT . Right . Just $ x'
Left x' -> EitherMaybeT . Left $ x'
if5EitherMaybe :: Int -> EitherMaybeT String Float
if5EitherMaybe x = do
x' <- liftMaybe $ is0 x
x'' <- liftEither $ isMultipleOf5 x'
return ((fromIntegral x'') / 5.0)
if5EitherMaybeNotTransformed :: Int -> EitherMaybeT String Float
if5EitherMaybeNotTransformed x = do
case (is0 x) of
Just x' -> case (isMultipleOf5 x) of
Right x'' -> liftEither $ Right $ fromIntegral x'' / 5.0
Left x'' -> liftEither $ Left x''
Nothing -> liftMaybe $ Nothing
main :: IO ()
main = do
print "Transformer:"
print . runEitherMaybe $ if5EitherMaybe 0
print . runEitherMaybe $ if5EitherMaybe 5
print . runEitherMaybe $ if5EitherMaybe 100
print . runEitherMaybe $ if5EitherMaybe 3
putStrLn ""
print "Non transformer:"
print . runEitherMaybe $ if5EitherMaybeNotTransformed 0
print . runEitherMaybe $ if5EitherMaybeNotTransformed 5
print . runEitherMaybe $ if5EitherMaybeNotTransformed 100
print . runEitherMaybe $ if5EitherMaybeNotTransformed 3
@chrissound
Copy link
Author

Output:

"Transformer:"
Right Nothing
Right (Just 1.0)
Right (Just 20.0)
Left "Value was not multiple of 5"

"Non transformer:"
Right Nothing
Right (Just 1.0)
Right (Just 20.0)
Left "Value was not multiple of 5"

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment