Reputation: 24613
I am trying to learn Haskell. In following code, I am trying to copy each element of a list to another through own function and then trying to print new list.
orilist = ["a", "b", "c"]
mylist = []
addfn ss = do -- trying to add sent string ss to mylist
let mylist = ss:mylist
return ()
main = do
mapM_ addfn orilist -- trying to send each element of orilist to addfn
mapM_ putStrLn mylist -- trying to print each element of mylist
return () -- no error but nothing is printed
The code runs without any error but nothing is printed. Where is the problem? Thanks for your help.
Upvotes: 0
Views: 66
Reputation: 477437
Your addfn
will not do anything, well it only returns a unit ()
. Indeed, your addfn
function:
addfn ss = do -- trying to add sent string ss to mylist
let mylist = ss:mylist
return ()
Is equivalent to:
addfn _ = return ()
since you never use mylist
. If you would use mylist
, it will be an infinite list that contains [ss, ss, …]
.
In Haskell there are no assignments: you do not assign a value to a variable, you declare a variable. Once a variable has a value, you can never alter that value. So even if if there was a variable named mylist
earlier, it would still not use that variable.
After you used mapM_ addfn orilist
, each addfn
will have returned ()
, and have not changed the state of anything, hence the list remains empty.
In your comment, you look to read the first line of each file. You can do that, for example by writing a function that reads the first line of a file:
import System.IO(IOMode(ReadMode), withFile, hGetLine)
readFirstLine :: FilePath -> IO String
readFirstLine fp = withFile fp ReadMode hGetLine
Then we can for example obtain a list of first lines of files with:
main :: IO ()
main = do
d <- mapM readFirstLine ["foo.txt", "bar.txt"]
print d
Upvotes: 4
Reputation: 116174
addfn ss = do -- trying to add sent string ss to mylist
let mylist = ss:mylist
return ()
This defined a local binding mylist
to be the infinite list ss:ss:ss:...
. Then, it's not used, so this definition is irrelevant. Hence, the code is equivalent to:
addfn ss = return ()
which is a no-op.
Haskell is not an imperative language. You are probably trying to modify the global variable mylist
, but that's impossible. Once you define mylist = []
, it will be []
forever.
You could do this instead:
orilist = ["a", "b", "c"]
main = do
let mylist = orilist
mapM_ putStrLn mylist -- trying to print each element of mylist
Or even
orilist = ["a", "b", "c"]
main = mapM_ putStrLn orilist
Another example: suppose we want to start with an empty list and, for 10 times, reverse it and append its length. We can do this as follows, using recursion:
doOnce oldList = reverse oldList ++ [length oldList]
newList = go 0 []
where go 10 list = list
go n list = go (n+1) (reverse list ++ [length list])
This is very inefficient, but I hope but you get the idea.
Upvotes: 3