Skip to content

Instantly share code, notes, and snippets.

@rubenpieters
Created January 10, 2018 20:51
Show Gist options
  • Select an option

  • Save rubenpieters/42fd378331a7282ea5e7efd31c92d610 to your computer and use it in GitHub Desktop.

Select an option

Save rubenpieters/42fd378331a7282ea5e7efd31c92d610 to your computer and use it in GitHub Desktop.

Revisions

  1. rubenpieters created this gist Jan 10, 2018.
    152 changes: 152 additions & 0 deletions Main.purs
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,152 @@
    module Main where

    import Prelude

    import Data.Set as S
    import Data.Array
    import Data.Lazy
    import Data.Maybe
    import Data.Tuple

    import Control.Monad.Eff (Eff)
    import Control.Monad.Writer

    import Unsafe.Coerce (unsafeCoerce)

    import TryPureScript (DOM, h1, h2, p, text, list, indent, link, render, code)

    -- the cheat:

    undef :: forall a. a
    undef = unsafeCoerce "oops!"

    -- Program 1 - inspecting gets and puts as Set/StrMap

    prog1 :: forall f r a.
    Monad f =>
    { get :: String -> f a
    , put :: String -> a -> f Unit | r } ->
    a -> f (Array a)
    prog1 k mouse = do
    f <- k.get "Cats"
    s <- k.get "Dogs"
    k.put "Mice" mouse
    t <- k.get "Cats"
    pure [f, s, t]

    get1 :: forall a. String -> Writer (Tuple (S.Set String) (S.Set (Tuple String Int))) a
    get1 key = writer (Tuple undef (Tuple (S.singleton key) (S.empty)))

    put1 :: forall a. String -> Int -> Writer (Tuple (S.Set String) (S.Set (Tuple String Int))) a
    put1 key value = writer (Tuple undef (Tuple (S.empty) (S.singleton (Tuple key value))))

    inspect1 :: (Tuple (S.Set String) (S.Set (Tuple String Int)))
    inspect1 = snd $ runWriter $ prog1 {get:get1, put:put1} 1

    inspect1_unsafe :: Array Int
    inspect1_unsafe = fst $ runWriter $ prog1 {get:get1, put:put1} 1

    -- Program 2 - Laziness

    prog2_strict :: forall f r a.
    Monad f =>
    { get :: String -> f (Maybe a)
    , put :: String -> a -> f Unit | r } ->
    a -> f (Array a)
    prog2_strict k mouse = do
    f <- k.get "Cats"
    s <- k.get "Dogs"
    k.put "Mice" mouse
    t <- k.get "Cats"
    pure (catMaybes [f, s, t])

    prog2_lazy :: forall f r a.
    Monad f =>
    { get :: String -> f (Maybe a)
    , put :: String -> a -> f Unit | r } ->
    a -> f (Lazy (Array a))
    prog2_lazy k mouse = do
    f <- k.get "Cats"
    s <- k.get "Dogs"
    k.put "Mice" mouse
    t <- k.get "Cats"
    pure (defer (\_ -> catMaybes [f, s, t]))

    -- uncomment and open console to see crash
    --inspect2_strict :: (Tuple (S.Set String) (S.Set (Tuple String Int)))
    --inspect2_strict = snd $ runWriter $ prog2_strict {get:get1, put:put1} 1

    inspect2_lazy :: (Tuple (S.Set String) (S.Set (Tuple String Int)))
    inspect2_lazy = snd $ runWriter $ prog2_lazy {get:get1, put:put1} 1

    -- Program 3 - inspecting gets and puts as Set/Set

    prog3 :: forall f r a.
    Monad f =>
    { get :: String -> f a
    , put :: String -> a -> f Unit | r } ->
    f (Array a)
    prog3 k = do
    f <- k.get "Cats"
    s <- k.get "Dogs"
    k.put "Mice" f
    t <- k.get "Cats"
    pure [f, s, t]

    get2 :: forall a. String -> Writer (Tuple (S.Set String) (S.Set String)) a
    get2 key = writer (Tuple undef (Tuple (S.singleton key) (S.empty)))

    put2 :: forall a. String -> Int -> Writer (Tuple (S.Set String) (S.Set String)) a
    put2 key value = writer (Tuple undef (Tuple (S.empty) (S.singleton key)))

    inspect3 :: (Tuple (S.Set String) (S.Set String))
    inspect3 = snd $ runWriter $ prog3 {get:get2, put:put2}

    -- Program 4 - turn off logging and inspecting

    prog4 :: forall f r a.
    Monad f =>
    Show a =>
    { get :: String -> f a
    , put :: String -> a -> f Unit
    , log :: String -> f Unit | r } ->
    a -> f (Array a)
    prog4 k mouse = do
    f <- k.get "Cats"
    k.log ("Cats: " <> show f)
    s <- k.get "Dogs"
    k.log ("Dogs: " <> show s)
    k.put "Mice" mouse
    t <- k.get "Cats"
    k.log ("Cats: " <> show t)
    pure [f, s, t]

    log1 :: forall f a. Applicative f => String -> f a
    log1 s = pure undef

    inspect4 :: (Tuple (S.Set String) (S.Set (Tuple String Int)))
    inspect4 = snd $ runWriter $ prog4 {get:get1, put:put1, log:log1} 1

    -- mismatched handler and computation

    inspect3_mismatched :: (Tuple (S.Set String) (S.Set (Tuple String Int)))
    inspect3_mismatched = snd $ runWriter $ prog3 {get:get1, put:put1}

    -- output

    main :: Eff _ Unit
    main = render $ fold
    [ h1 (text "Output:")
    , h2 (text $ "inspect prog1: ")
    , p (text $ show inspect1)
    , h2 (text $ "'run' prog1 (unsafe): ")
    , p (text $ show inspect1_unsafe)
    , h2 (text $ "inspect lazy prog2: ")
    , p (text $ show inspect2_lazy)
    , h2 (text $ "inspect prog3: ")
    , p (text $ show inspect3)
    , h2 (text $ "inspect prog4: ")
    , p (text $ show inspect4)
    , h2 (text $ "inspect progx: ")
    , p (text $ show inspect3_mismatched)
    ]