从列表中删除的项目又回来了

Fly*_*man 2 io monads haskell loops

我想从列表中删除一个项目,但它又回来了。

main = do
  let y = ["aa","bb","cc","dd","ee","ff"]
  let n = length y
  replicateM_ (n-1) (deleteWord y)

deleteWord y = do
  putStrLn "Write a word: "
  word <- getLine
  let new_y = delete word y
  print new_y
Run Code Online (Sandbox Code Playgroud)

输出:

*Main> main
Write a word: 
aa
["bb","cc","dd","ee","ff"]
Write a word: 
bb
["aa","cc","dd","ee","ff"]
Write a word: 
cc
["aa","bb","dd","ee","ff"]
Run Code Online (Sandbox Code Playgroud)

我希望 和"aa"保持"bb"删除状态,并且不再回到列表中。

jpm*_*ier 8

正如评论中所解释的,该y值一旦定义,就像 Haskell 中的每个值一样是不可变的。

\n

但是有一个单子库函数,nest :: Monad m => Int -> (a -> ma) -> a -> ma,它允许您将一个动作的结果重新注入到同一个动作中,例如一些次。

\n

为了使用它,您的基本操作需要返回一个结果

\n
$ ghci\nGHCi, version 8.8.4: https://www.haskell.org/ghc/  :? for help\n...\n \xce\xbb>\n \xce\xbb> import Data.List(delete)\n \xce\xbb> import Control.Monad.HT(nest)\n \xce\xbb> \n \xce\xbb> \n \xce\xbb> :{\n|\xce\xbb> deleteWord y = do\n|\xce\xbb>   putStrLn "Write a word: "\n|\xce\xbb>   word <- getLine\n|\xce\xbb>   let new_y = delete word y\n|\xce\xbb>   print new_y\n|\xce\xbb>   return new_y  -- HERE !!!\n|\xce\xbb> :}\n \xce\xbb> \n \xce\xbb> :type deleteWord\n deleteWord :: [String] -> IO [String]\n \xce\xbb> \n \xce\xbb> action3 = nest 3 deleteWord\n \xce\xbb> \n \xce\xbb> :type action3\n action3 :: [String] -> IO [String]\n \xce\xbb> \n
Run Code Online (Sandbox Code Playgroud)\n

那么让我们尝试运行该嵌套操作:

\n
 \xce\xbb> \n \xce\xbb> res3 <- action3 ["aa","bb","cc","dd","ee","ff"]\nWrite a word: \nff\n["aa","bb","cc","dd","ee"]\nWrite a word: \naa\n["bb","cc","dd","ee"]\nWrite a word: \ndd\n["bb","cc","ee"]\n \xce\xbb> \n \xce\xbb>\n \xce\xbb> res3\n["bb","cc","ee"]\n \xce\xbb> \n
Run Code Online (Sandbox Code Playgroud)\n

附录:

\n

对于刚开始的 Haskell 程序员来说,源代码nest可能并不完全具有启发性。但库源代码的主要目标是最大限度地提高运行时效率。

\n

可以编写一个更简单的版本,并明确递归:

\n
myNest :: Monad m => Int -> (a -> m a) -> a -> m a\nmyNest n fn a0 =\n    if (n <= 0) then  (return a0)\n                else  do\n                          a1 <- fn a0\n                          myNest (n-1) fn a1\n
Run Code Online (Sandbox Code Playgroud)\n