Skip to content

Instantly share code, notes, and snippets.

@codecontemplator
Last active September 26, 2021 16:11
Show Gist options
  • Save codecontemplator/1ea5c8d68f58a6d5fe3a840bbcd94229 to your computer and use it in GitHub Desktop.
Save codecontemplator/1ea5c8d68f58a6d5fe3a840bbcd94229 to your computer and use it in GitHub Desktop.
{-# LANGUAGE FlexibleInstances, UndecidableInstances, InstanceSigs, NoImplicitPrelude #-}
import Prelude(id, ($), (.), putStrLn, undefined)
-- The standard(?) haskell monad definition
class StdMonad m where
(>>=) :: m a -> (a -> m b) -> m b
return :: a -> m a
-- The more mathematical monad defintion
class Functor f where
fmap :: (a -> b) -> (f a -> f b)
class Functor m => MathMonad m where
join :: m (m a) -> m a
jreturn :: a -> m a
-- A MathMonad is a StdMonad
instance MathMonad m => StdMonad m where
ma >>= f = join $ fmap f ma
return = jreturn
-- A StdMonad is a MathMonad (and a Functor)
instance StdMonad m => Functor m where
fmap f = \ma -> ma >>= (return . f)
{-
-- duplicate instance
instance StdMonad m => MathMonad m where
join :: StdMonad m => m (m a) -> m a
join mma = mma >>= id
jreturn = return
-}
-- Monads defined using Kleisli arrows
class KleisliMonad m where
kid :: a -> m a
(>=>) :: (a -> m b) -> (b -> m c) -> (a -> m c)
-- A StdMonad (and also MathMonad since they are equivalent) is a KleisliMonad
instance StdMonad m => KleisliMonad m where
f >=> g = \a -> let mb = f a in mb >>= g
kid = return
-- A KleisliMonad is also a StdMonad
{-
-- duplicate instance
instance KleisliMonad m => StdMonad m where
ma >>= f = id >=> f $ ma
return = kid
-}
-- Defintion of monad via Free
-- ref: https://www.tweag.io/blog/2018-02-05-free-monads/
data Free f a =
Pure a
| Free (f (Free f a))
class Functor m => FMonad m where
monad :: Free m a -> m a
instance FMonad m => MathMonad m where
jreturn a = monad $ Pure a
join = monad . Free . fmap (Free . fmap Pure)
-- fmap :: a -> b -> m a -> m b
-- monad :: Free m a -> m a
-- Pure :: a -> Free m a
-- Free :: m (Free m a) -> Free m a
-- fmap Pure :: m a -> m (Free m a)
-- Free . fmap Pure :: m a -> Free m a
-- fmap (Free . fmap Pure) :: m (m a) -> m (Free m a)
-- Free . fmap (Free . fmap Pure) :: m (m a) -> Free m a
-- monad . Free . fmap (Free . fmap Pure) :: m (m a) -> m a
-- join :: m (m a) -> m a
instance MathMonad m => FMonad m where
monad (Pure a) = jreturn a
monad (Free m) = join $ fmap monad m
main = putStrLn "type checked"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment