As @Jubobs already said in the comments - no you cannot, but this is not necessarily (always) inefficient.
Before starting with some explanation I'd like to remind you of Donald Knuth and his saying that the root of all evil is premature optimization. So try to write a correct program and worry about performance later - when you run into bottlenecks (and be assured haskell has good tooling to detect bottlenecks!).
Example
Say you have an infinite list [1..]
and you want to append 5
you can still do that in haskell. Let us fire up ghci and observe some things.
> ghci
GHCi, version 8.0.2: http://www.haskell.org/ghc/ :? for help
Prelude> let a = [1..] ++[5] :: [Int]
first of all we notice - that let
-bindings work lazily and nothing is printed (yet). We can even go further and inspect how far a
is evaluated.
Prelude> :sprint a
a = _
while an expression like filter (== 5) a
will never terminate, we still can do useful stuff with our list a
.
Prelude> let b = map (+2) a
Prelude> take 10 b
[3,4,5,6,7,8,9,10,11,12]
and inspecting a
again.
Prelude> :sprint a
a = 1 : 2 : 3 : 4 : 5 : 6 : 7 : 8 : 9 : 10 : _
we have only evaluated the first ten elements.
Concluding this example we see - even if you "append" 5
it might never be used - and thus the "appending" will have never happened, which is more efficient than if we had a cheap "appending" that had happened.
(Note that this lazyness, introduces a bit of a memory overhead that can lead into troubles see Lazy Evaluation - Space Leak for more on that.)
Alternatives
As others have already said - there are alternatives to using good old lists.
- If you append often but use the list as an "accumulator" - it might be a good idea to just pre-pend and reverse the list before returning. which is
O(1)
for all (:)
operations and O(n)
for the reverse - compared to O(n)
for each (++)
step.
Use different data structures:
- difference list: which you can read up on Learn you a haskell for great good quoting from there:
The difference list equivalent of a list like [1,2,3]
would be the function \xs -> [1,2,3] ++ xs
. A normal empty list is []
, whereas an empty difference list is the function \xs -> [] ++ xs
.
Sequence
: from Data.Sequence which supports efficient prepend
/append
-operations and lookup for elements at the edges.
$ stack ghci --package containers
Prelude> import Data.Sequence
Prelude Data.Sequence> let a = fromList [1..4] :: Seq Int
Prelude Data.Sequence> (a |> 5)
fromList [1,2,3,4,5]
Prelude Data.Sequence> 0 <| (a |> 5)
fromList [0,1,2,3,4,5]
Set
- which is not ordered like lists, but nevertheless supports efficient (O(log n)
) inserts, but only allows for unique inserts.
$ stack ghci --package containers
Prelude> import Data.Set
Prelude Data.Set> let a = fromList [1..4] :: Set Int
Prelude Data.Set> insert 5 a
fromList [1,2,3,4,5]
Prelude Data.Set> insert 4 a
fromList [1,2,3,4]