Help using a state monad

Tom Bevan tom@regex.com.au
14 Jan 2002 16:58:15 +1100


--=-cSZMBXDBPCagvkaSVqyo
Content-Type: text/plain
Content-Transfer-Encoding: 7bit

Hi all,

I'm trying to get a feel for how monads might be used in a Haskell
program and develop an approach that would be useful for larger 
projects.
I have tried to model in miniture a programme which takes input from
'standard in' and processes it against an internal state and then
returns the processed result to 'standard out'.
My problem is that, becuase of the way I have constructed the programme
'standard out' lags behind by one character.
I'm hoping that someone might have a better design they could share with
me.

Tom.




--=-cSZMBXDBPCagvkaSVqyo
Content-Disposition: attachment; filename=scratch.hs
Content-Transfer-Encoding: quoted-printable
Content-Type: text/plain; charset=ISO-8859-1

-- State monad

type Register =3D Bool

data State a =3D State ( Register -> ( Register , a ) )

instance Monad State where
 return a =3D State ( \r -> ( r , a ))
 (State st) >>=3D f =3D State ( \r -> let=20
 				     ( newst, x ) =3D st r
 				     (State trans) =3D f x
			   	     in=20
				     trans newst )=20

-- Function to check the state
isOn :: State Bool=20
isOn =3D State ( \r -> ( r , r ) )
-- Function to toggle the state.
toggle :: State ()
toggle =3D State ( \r -> ( not r , () ) )

--Simple function to output upper or
--lower case characters based on the state.
tuUpper :: Register -> Char -> Char
tuUpper True c =3D toUpper c
tuUpper	_ c =3D c


main :: IO ()

main =3D interact process

--Process the input
mProcess :: String -> State String
mProcess (s:sx) =3D do b <- isOn
		     if ( s =3D=3D 't' )
		        then toggle
			else return ()
		     appOut (tuUpper b s) (mProcess sx)

--Compose the output into a string
appOut :: Char -> State String -> State String
appOut c m =3D do str <- m
		return ([c] ++ str)

--Extracts the answer from
--a series of monadic calculations
extract :: State a -> a
extract (State k) =3D snd ( k False )

process =3D extract.mProcess=20

--=-cSZMBXDBPCagvkaSVqyo--