[Haskell-cafe] state in the continuation monad...

Ralf Laemmel Ralf.Laemmel at cwi.nl
Fri Jul 2 10:15:15 EDT 2004

-------------- next part --------------
{-# OPTIONS -fglasgow-exts #-}


Regarding Keean's posting ...
I wonder whether perhaps a more basic step is to understand
how type-changing monadic computations can be understood.
By this I mean, that the effects model by the monad can change
their type as part of the computation. Such a monad would be
parameterised by effect types a b, where a is the type of the
effect before computation and b is the type after computation.

The following code illustrates this idea.


Warm-up: we compute a normal sequence of monadic ticks,
and we get back the final state and the value of the computation.

ghci6.2> ticks

Demo: we do the same with heterogeneous monadic operations,
and we get back the type-level natural for the final state etc.

ghci6.2> hTicks
         (HSucc (HSucc (HSucc HZero)),2)


-- Value-level (i.e., normal) state monads ----------------------------------

-- A silly state monad
data State s a = State (s -> (s,a))
unState (State f) = f

instance Monad (State s)
  return a = State (\s -> (s,a))
  c >>= f  = State (\s ->
                      let (s',a)  = unState c s
                      in unState (f a) s' 

-- Start with state 0
runZero :: State Int a -> (Int,a)
runZero f = unState f 0

-- Tick and return original value
tick :: State Int Int
tick = State (\s -> (s+1,s)) 

-- Do a sequence of computations
ticks = runZero (    tick
                 >>= const tick 
                 >>= const tick)

-- Now in a type-driven fashion ---------------------------------------------

-- A state monad with type-changing states
data HState s s' a = HState (s -> (s',a))
unHState (HState f) = f

-- A class for heterogeneous returns
class HReturn m x
  hReturn :: a -> m x x a

instance HReturn HState s
  hReturn a = HState (unState (return a))

-- A class for heterogeneous binds
class HBind m x y z
  hBind :: m x y a -> (a -> m y z b) -> m x z b

instance HBind HState x y z
  c `hBind` f  = HState (\s ->
                           let (s',a)  = unHState c s
                           in unHState (f a) s'

-- We use type-level naturals for different state types
data HZero   = HZero    deriving Show
data HSucc x = HSucc x  deriving Show

class HNat x 
  hNat :: x -> Int

instance HNat HZero
  hNat HZero = 0

instance HNat n => HNat (HSucc n) 
  hNat (HSucc n) = 1 + hNat n

-- Start with state HZero
runHZero :: HState HZero n a -> (n,a)
runHZero f = unHState f HZero

-- Tick and return original value
htick :: HNat n => HState n (HSucc n) Int
htick = HState (\s -> (HSucc s,hNat s)) 

-- Do a sequence of computations
hTicks = runHZero (        htick
                   `hBind` const htick 
                   `hBind` const htick)

-- Should print: ((3,2),(HSucc (HSucc (HSucc HZero)),2))

main = print (ticks,hTicks)

More information about the Haskell-Cafe mailing list