如何以不可变的方式保存对列表所做的更改



我需要向用户请求输入,用它做些什么,请求下一个输入,并用它做点什么,但我仍然需要考虑上一个输入。

我想(以OOP的方式(将所有input <- getLine保存到一个列表中,然后能够对该列表进行更改(并存储它们(,但我不能这样做,因为haskell中的东西是不可变的。

main =  do
args <- getArgs
contents <- readFile $ head args
putStrLn contents
let inputs = []  --THIS
forever $ do
putStrLn $ "Filtering: " ++ appendFilters inputs
input <- getLine
let inputs = updateInputs inputs input --THIS
newInput <- getUserInputs inputs input
putStrLn $ unlines (filterContent (lines contents) newInput)

从函数式编程的角度来看,我该如何做到这一点?

编辑:

所以我的程序应该做的是:

  1. 从文件中读取内容
  2. 获取用户输入以便仅显示包含这些单词的行
  3. 获取更多用户输入,如果input == "pop",则删除最后一个筛选器,否则添加到筛选词列表中
  4. 如果用户试图弹出一个空的过滤器列表,请退出程序

首先,您可以在Haskell中拥有可变值,您只需要在IO monad中进行所有更新。我们通常会避免这种情况,但如果您的代码都是关于IO交互的,那么它可能是最简单的解决方案。

import Data.IORef
main =  do
args <- getArgs
contents <- readFile $ head args
putStrLn contents
inputs <- newIORef []
forever $ do
currentInputs <- readIORef inputs
putStrLn $ "Filtering: " ++ appendFilters currentInputs
input <- getLine
updateInputs inputs input
newInput <- getUserInputs inputs input
putStrLn $ unlines (filterContent (lines contents) newInput)

功能性更强的替代方案通常是通过递归"循环"显式传递有状态变量的更新版本。然后您将无法使用forever,但很容易将其更改为手动递归:

main =  do
args <- getArgs
contents <- readFile $ head args
putStrLn contents
let loop inputs = do
putStrLn $ "Filtering: " ++ appendFilters inputs
input <- getLine
newInput <- getUserInputs inputs input
putStrLn $ unlines (filterContent (lines contents) newInput)
loop $ updateInputs inputs input
loop []

最新更新