[Haskell-beginners] I wrote a state monad example - help me make it more Haskellic
Rohit Garg
rpg.314 at gmail.com
Sun Jul 24 05:56:30 CEST 2011
Hi Aditya,
Your modifications are very nice. I didn't know about the modify
function. Now the code looks much better.
Thanks.
On Sun, Jul 24, 2011 at 12:55 AM, aditya siram <aditya.siram at gmail.com> wrote:
> Hi Rohit,
> I've refactored your program a little bit. Hope you don't mind. The
> main change I made was, since there can only be four registers, to
> create explicit datatypes for each register and turn your RegisterFile
> datatype into a 4-tuple. The corresponding setter and getter,
> store_operand and get_operand have also been changed to reflect the
> new datatypes. This way there can never be errors with list indices
> etc.
>
> I've also used two new State monad functions of which you might be unaware:
> 1. modify :: modifies state with the given function.
> 2. mapM_ :: is like a "map" but takes a monadic action and applied it
> to the given ist.
>
> The output is stil the same as your code, but I've added a little type safety.
>
> I haven't covered every detail of the changes but if you're reading
> through it and get stuck, please let me know.
>
> -deech
>
> import Control.Monad.State
>
> type RegisterVal = Int
> data RegisterID = R1 | R2 | R3 | R4 deriving Show
> type RegisterFile = (RegisterVal, RegisterVal, RegisterVal, RegisterVal)
>
> get_operand :: RegisterFile -> RegisterID -> RegisterVal
> get_operand (r1,_,_,_) R1 = r1
> get_operand (_,r2,_,_) R2 = r2
> get_operand (_,_,r3,_) R3 = r3
> get_operand (_,_,_,r4) R4 = r4
>
> store_operand :: RegisterFile -> RegisterID -> RegisterVal -> RegisterFile
> store_operand (r1,r2,r3,r4) r v = case r of
> R1 -> (v,r2,r3,r4)
> R2 -> (r1,v,r3,r4)
> R3 -> (r1,r2,v,r4)
> R4 -> (r1,r2,r3,v)
>
> eval_inst :: Instruction -> RegisterFile -> RegisterFile
> eval_inst inst rf = let store_op' = store_operand rf
> get_op' = get_operand rf
> in
> case inst of
> Add dest rid1 rid2 -> store_op' dest (get_op'
> rid1 + get_op' rid2)
> Sub dest rid1 rid2 -> store_op' dest (get_op'
> rid1 - get_op' rid2)
> Mov dest rid -> store_op' dest (get_op' rid)
> Movc dest v -> store_op' dest v
>
> --destination comes first
> data Instruction = Add RegisterID RegisterID RegisterID
> | Sub RegisterID RegisterID RegisterID
> | Mov RegisterID RegisterID
> | Movc RegisterID RegisterVal
> deriving (Show)
>
> initial_rf :: RegisterFile
> initial_rf = (0,0,0,0)
>
> insts = [Movc R1 231, Movc R2 (-42), Add R3 R2 R1, Sub R4 R2 R1]
>
> execute_program2 :: [Instruction] -> State RegisterFile ()
> execute_program2 = mapM_ (modify . eval_inst)
>
> main :: IO ()
> main = putStrLn $ show $ execState (execute_program2 insts) initial_rf
>
--
Rohit Garg
http://rpg-314.blogspot.com/
More information about the Beginners
mailing list