Reputation: 911
I have a list of integers, I need to append elements to it at different times.
let xs =[]::[Int]
usually appending elements to this would be like:
1:xs
but when using IO in a function, it doesn't seem to work within a do block and gives errors, and
let xs = [1]
let xs=(2:xs)
results in an infinite list like [1,2,2,2,2,.....] What can I do to correct this?
Upvotes: 0
Views: 654
Reputation: 122429
For completeness, if you really want to "assign" imperatively in the IO monad (which is what you seemed to be getting at), you could. You would use a mutable cell (a "reference"); which in the IO monad, would be IORef
:
import Data.IORef
do xs <- newIORef [1]
temp <- readIORef xs
writeIORef xs (2 : temp)
However, doing so would be highly unidiomatic and you almost never want to write stuff like this.
Upvotes: 2
Reputation: 68152
In Haskell, let
bindings are recursive by default. So the two xs
in the second line refer to themselves. The solution is to not shadow the xs
binding:
let xs = [1]
let xs' = 2:xs
Remember that Haskell does not allow mutation. So the second let
binding does not mean changing the value of xs
--it means creating a new variable that just also happens to be called xs
.
Just to clarify: xs'
is completely separate from xs
. Haskell lets you use '
in variable names. xs'
here could as easily be xs2
. The '
is pronounced "prime" (e.g. exes prime) and taken from math where things like x
, x'
and x''
are common.
A side note: :
prepends to a list; appending means putting the element on the end.
Also, your let xs = 2:xs
results in [2,2,2...]
rather than [1,2,2,2...]
.
Upvotes: 5
Reputation: 24802
You seem to have a fundamental misunderstanding about lists in Haskell. The lists are always immutable, so there is no way to add new elements to an existing list. I.e. You can only create new lists.
So, accordingly, the a:b
operator never adds an element to a list, but creates a new list where a
is the first element, which is followed by the existing list b
.
When you say:
let xs = 2 : xs
You are saying that xs
is a list where the first element is 2
and the rest of the list is xs
itself, which logically results in an infinite list of 2's. In the context of this question, it's irrelevant whether you are in the IO monad or not.
So given the above, you need to do something like
let xs1 = [1]
let xs2 = 2:xs1
let xs3 = 3:xs2
But of course, this is the same as simply doing
let xs3 = [3,2,1]
So you really need to give some more context on what kind of list you want to build and why.
Upvotes: 7
Reputation: 53017
Don't make your list be recursive?
let xs = [1]
let foo=(2:xs) -- non-recursive
Upvotes: 0