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?

+3


source to share


1 answer


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 []

      

+4


source







All Articles