I want to remove an item from a list, but it comes back.
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
OUTPUT=
*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"]
I want that the "aa"
and "bb"
stay removed and not come back into the list.
CodePudding user response:
As explained in the comments, the y
value, once defined, is immutable like every value in Haskell.
But there is a monadic library function, nest :: Monad m => Int -> (a -> m a) -> a -> m a, that allows you to re-inject the result of an action into that very same action, for some number of times.
In order to use it, your base action needs to return a result:
$ ghci
GHCi, version 8.8.4: https://www.haskell.org/ghc/ :? for help
...
λ>
λ> import Data.List(delete)
λ> import Control.Monad.HT(nest)
λ>
λ>
λ> :{
|λ> deleteWord y = do
|λ> putStrLn "Write a word: "
|λ> word <- getLine
|λ> let new_y = delete word y
|λ> print new_y
|λ> return new_y -- HERE !!!
|λ> :}
λ>
λ> :type deleteWord
deleteWord :: [String] -> IO [String]
λ>
λ> action3 = nest 3 deleteWord
λ>
λ> :type action3
action3 :: [String] -> IO [String]
λ>
So let's try to run that nested action:
λ>
λ> res3 <- action3 ["aa","bb","cc","dd","ee","ff"]
Write a word:
ff
["aa","bb","cc","dd","ee"]
Write a word:
aa
["bb","cc","dd","ee"]
Write a word:
dd
["bb","cc","ee"]
λ>
λ>
λ> res3
["bb","cc","ee"]
λ>
Addendum:
The source code for nest
is perhaps not exactly illuminating for a beginning Haskell programmer. But the primary goal for library source code is to maximize runtime efficiency.
It is possible to write a simpler version with recursion made explicit:
myNest :: Monad m => Int -> (a -> m a) -> a -> m a
myNest n fn a0 =
if (n <= 0) then (return a0)
else do
a1 <- fn a0
myNest (n-1) fn a1
CodePudding user response:
Coded with direct recursion; with minimal changes to your code:
main = do
let y = ["aa","bb","cc","dd","ee","ff"]
let n = length y
-- replicateM_ (n-1) (deleteWord y)
deleteWord n y
deleteWord k y | k <= 0 = return ()
deleteWord k y = do --<<----<<---.
putStrLn "Write a word: " -- |
word <- getLine -- |
let new_y = delete word y -- |
print new_y -- |
deleteWord (k-1) new_y --->>---'
using the updated value, new_y
, in the recursive invocation.