Skip to content

Instantly share code, notes, and snippets.

@wuct
Created December 2, 2017 09:00
Show Gist options
  • Save wuct/e2a4d5054a2cb1926bdf66a5123c4e86 to your computer and use it in GitHub Desktop.
Save wuct/e2a4d5054a2cb1926bdf66a5123c4e86 to your computer and use it in GitHub Desktop.
A Writer Monad implementation without introduction Monad Transformer.
module Main where
import Prelude
import Data.Tuple (Tuple(..), snd)
import Data.Monoid (class Monoid, mempty)
import Control.Monad.Eff.Console (logShow)
import TryPureScript (render, withConsole)
newtype Writer w a = Writer (Tuple a w)
runWriter :: forall w a. Writer w a -> Tuple a w
runWriter (Writer t) = t
execWriter :: forall w a. Writer w a -> w
execWriter (Writer t) = snd t
instance functorWriter :: Functor (Writer w) where
map f (Writer (Tuple a w)) = Writer (Tuple (f a) w)
instance applyWriter :: Semigroup w => Apply (Writer w) where
apply (Writer (Tuple f w')) (Writer (Tuple a w)) = Writer (Tuple (f a) (w' <> w))
instance applicativeWriter :: Monoid w => Applicative (Writer w) where
pure a = Writer (Tuple a mempty)
instance bindWriter :: Semigroup w => Bind (Writer w) where
bind (Writer (Tuple a w)) f = let (Tuple a' w') = runWriter (f a) in Writer (Tuple a' (w <> w'))
instance monadWriter :: Monoid w => Monad (Writer w)
tell :: forall w. w -> Writer w Unit
tell w = Writer (Tuple unit w)
main = render <=< withConsole $ do
logShow $ runWriter $ Writer (Tuple 1 "log 1")
logShow $ runWriter $ (\x -> x + 1) <$> Writer (Tuple 1 "log 1")
logShow $ runWriter $ Writer (Tuple (+) "log +, ") <*> Writer (Tuple 1 "log 1, ") <*> Writer (Tuple 2 "log 2")
logShow $ runWriter $ pure (+) <*> Writer (Tuple 1 "log 1, ") <*> Writer (Tuple 2 "log 2")
logShow $ runWriter $ Writer (Tuple 1 "log 1, ") >>= (\x -> Writer (Tuple (x + 1) "log inc"))
logShow $ runWriter $ do
a <- Writer (Tuple 3 "log 3, ")
b <- Writer (Tuple 2 "log 2, ")
tell "log 2 * 3"
pure (a * b)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment