将IO与状态计算混合

时间:2014-10-01 14:47:47

标签: haskell

作为练习,我正在Haskell中编写一个命令行RPN计算器。这个想法是它会提示输入(数字或操作符)并打印出新的堆栈。我的计划是将状态列表存储在状态monad中,并对该列表执行计算。例如:

> 4
[4]
> 3
[3,2]
> 5
[5,3,2]
> +
[8, 2]

等等。

我首先尝试使用输入和放大器在State monad中建立列表。每个条目的输出。由于IO&组合,我已经陷入困境状态相同。我的问题是,我还需要对输入进行递归,以便在输入第一个数字后保持提示。

到目前为止,这是我的代码:

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

这是我目前得到的编译器错误:

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

有关如何构建这些功能的任何提示,以至于我没有组合IO&amp;状态?

1 个答案:

答案 0 :(得分:4)

我不确定你是否正在使用州,因为你想尝试一下,但你可以在没有“烦恼”的情况下实现这个状态。国家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 []