Skip to content

Instantly share code, notes, and snippets.

@patrl
Created June 15, 2020 21:15
Show Gist options
  • Save patrl/4db7bdeba3b18536431d1308c6fc31fa to your computer and use it in GitHub Desktop.
Save patrl/4db7bdeba3b18536431d1308c6fc31fa to your computer and use it in GitHub Desktop.

First, let's roll our own state monad. We'll treat assignments just as sequences of individuals.

{-# LANGUAGE TupleSections #-}

import Data.Bifunctor (first)
import Control.Applicative (liftA2)

type E = Int

type G = [E]

dom :: [E]
dom = [1..10]

newtype S a = S { runS :: G -> (a,G)}

instance Functor S where
    fmap f m = S $ \g -> first f (runS m g)
    
instance Applicative S where
    pure a = S (a,)
    m <*> n = S $ \g ->
        let (f,g') = runS m g
            (x,g'') = runS n g'
        in (f x,g'')
        
newtype SS a = SS { runSS :: G -> [(a,G)]}

instance Functor SS where
    fmap f m = SS $ \g -> first f <$> runSS m g
    
instance Applicative SS where
    pure a = SS $ (:[]) <$> (a,)
    m <*> n = undefined

instance Monad SS where
    return = pure
    m >>= k = SS $ \g ->
        let pairs = runSS m g
        in concat [(runSS $ k x) g' | (x,g') <- pairs ]
 
intro :: S E -> S E
intro m = S $ \g ->
    let (x,g') = runS m g
    in (x,x:g')

pro :: S E
pro = S $ \(x:g) -> (x,g)
test1 = ($ []) $ runS $ liftA2 (&&) (pure odd <*> (intro . pure $ 1)) (pure even <*> intro pro)
test1
test2 = ($ []) $ runS $ liftA2 (&&) (pure odd <*> (intro pro)) (pure even <*> intro (pure 1))
test2

Let's roll our own continuation monad:

newtype K b a = K { (>>-) :: (a -> b) -> b}

instance Functor (K b) where
    fmap f m = K $ \k -> m >>- (k . f)
    
instance Applicative (K b) where
    pure x = K $ \k -> k x
    m <*> n = K $ \k -> m >>- \f -> n >>- \x -> k (f x)
    
liftS :: S a -> SS a
liftS m = SS $ \g -> [runS m g]

lower :: K (SS a) (S a) -> SS a
lower m = (>>-) m liftS
anEvenInt :: SS E
anEvenInt = SS $ \g -> [(n,g)|n <- dom, even n]

Let's see how maximally polymorphic liftS and lower allow a violation of crossover.

"One is less than its successor"

($ []) $ runS $ (liftA2 (<)) (intro $ pure 1) ((pure succ) <*> pro)
($ []) $ runS $ (liftA2 (<)) ((pure succ) <*> pro) (intro $ pure 1)
obj = pure pure <*> (K $ (>>=) $ (liftS (intro $ pure 1)))

"A successor to it is greater than 1"

($ []) $ runSS $ lower $ (liftA2 $ liftA2 (>)) (pure $ ((pure succ) <*> pro)) obj
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment