Provided that don't know how do you to keep the state. Here just provide a simple example show how to use StateT
with reading characters from standard input.
Firstly, to define the advanceState
function as:
advanceState::StateT [Char] IO [Char]
advanceState = StateT readInput where
readInput cs = do c <- getChar
let newState = (c:cs)
return (newState, newState)
The function embedded in StateT
is readInput
, it has type:
[Char]->IO ([Char], [Char])
The first element of pair ([Char], [Char])
is input that what we want, and the second element of that is the "state" will pass to readInput
whenever advanceState
is called again.
Now, below is an example show how to use advanceState
:
getChar10::StateT [Char] IO [Char]
getChar10 = do s <- advanceState
if (length s) <= 10
then getChar10
else do put []
return (reverse s)
This example show how to get 10 character from standard input when the user press enter, note that put []
reset the state so that next call of advanceState
will not has the previous input.
Finally, we can play around with them:
playState::IO ()
playState = print =<< evalStateT loop [] where
loop = do s1 <- getChar10
s2 <- getChar10
return (s1 ++ "::" ++ s2)
The playState
function will print first 20 characters (included new line character \n, \r) whatever how many characters user has inputted before press enter. If input not enough 20 characters, playState
will request user to input more characters.