Mixing I / O with state computation
As an exercise, I am writing a command line RPN calculator in Haskell. The idea is that it will ask for input (number or operator) and print a new stack. My plan is to store a list of numbers in the state monad and perform calculations against that list. For example:
> 4
[4]
> 3
[3,2]
> 5
[5,3,2]
> +
[8, 2]
etc.
I start by just trying to create a list in a state monad with input and output on each record. I am already stuck due to the combination of IO and State in the same function. My problem is that I also need to overwrite the input to keep the prompt after entering the first number.
Here is my code:
module Main where
import Control.Monad.State
addEntry :: Int -> State [Int] Int
addEntry entry = do
entries <- get
put (entry : entries)
return entry
mainLoop :: [Int] -> IO ()
mainLoop entries = do
entry <- readLn
newEntries <- execState (addEntry entry) entries
print newEntries
mainLoop newEntries
main :: IO ()
main = do
print $ mainLoop []
and here is the compiler error I am currently getting:
src/Main.hs@14:28-14:42 Couldn't match type [Int] with βIO [Int]β
Expected type: State (IO [Int]) Int
Actual type: State [Int] Int β¦
src/Main.hs@14:44-14:51 Couldn't match expected type βIO [Int]β with actual type [Int] β¦
Any advice on how to structure these functions so that I don't mix IO and State?
source to share
I'm not sure if you are using the state because you want to try, but you can achieve the state itself without "bothering" the state monad.
module Main where
addEntry :: Int -> [Int] -> [Int]
addEntry = (:)
mainLoop :: [Int] -> IO ()
mainLoop entries = do
entry <- readLn
let newEntries = addEntry entry entries
print newEntries
mainLoop newEntries
main :: IO ()
main = mainLoop []
source to share