Monadification (variant 1)


Identity: Monadification
Category: Data MultiModule
Classifiers: data abstraction
Internal cross references:
External cross references:

Language: This has been described in terms of Haskell, but will apply to any language with type classes (and instances).

Description: Commonality in a data type is factored out by the introduction of a separate type which explicitly represents the different variants within the original type.

data Expr                
  = Lit Integer |             -- Literal integer value
    Vbl Var |                 -- Assignable variables
    Add Expr Expr |           -- Expression addition: e1+e2
    Assign Var Expr           -- Assignment: x:=e 

type Var = String

type Store = [ (Var, Integer) ]

lookup :: Store -> Var -> Integer
lookup st x = head [ i | (y,i) <- st, y==x ]

update :: Store -> Var -> Integer -> Store
update st x n = (x,n):st 

eval :: Expr -> Store -> (Integer, Store)   

eval (Lit n) st                             
  = (n,st)                                    


eval (Vbl x) st                              
  = (lookup st x,st)                          



eval (Add e1 e2) st                         
  = (v1+v2, st2)                              
    where                                       
    (v1,st1) = eval e1 st                       
    (v2,st2) = eval e2 st1                      

eval (Assign x e) st                        
  = (v, update st' x v)                       
    where                                       
    (v,st') = eval e st                         


data Expr                
  = Lit Integer |
    Vbl Var |
    Add Expr Expr |
    Assign Var Expr 

type Var = String

type Store = [ (Var, Integer) ]

lookup :: Store -> Var -> Integer
lookup st x = head [ i | (y,i) <- st, y==x ]

update :: Store -> Var -> Integer -> Store
update st x n = (x,n):st

evalST :: Expr -> State Store Integer

evalST (Lit n)
  = do
    return n

evalST (Vbl x) 
   = do
    st <- get
    return (lookup st x)

evalST (Add e1 e2)
   = do
    v1 <- evalST e1
    v2 <- evalST e2
    return (v1+v2)

evalST (Assign x e)
  = do
    v  <- evalST e
    st <- get
    put (update st x v)
    return v

General comment:

This refactoring introduces a particular instance of the Monad class, based on uses of the instance functions. Other monadifications will introduce use of a general monad into non-monadic code (i.e. code which uses the identity monad).

Left to right comment:

The code on the LHS explicitly threads the state through the computation. Since such a form of computation is represented by the State monad, this conversion can be seen as folding against the definitions in the declaration of State as an instance of Monad.

Right to left comment:

Moving from RHS to LHS makes the state manipulation explicit; this might precede further modifications.

Left to right conditions:

There is no condition on this.

Right to left conditions:

There is no restriction on the right to left transition.