Efficiently merge two lists
I'm currently learning Haskell, and working with List
.
According to the HaskellWiki, if I wanted to merge two lists together, I would write:
list1 ++ list2
However, according to this answer, using ++ on a large list would be inefficient.
From researching, I came across this SO page, but that question requires a specific requirement for the output of the List
.
What I tried:
Suppose if I had two lists of numbers (for this example, assume that both lists are large enough that using ++
would be inefficient as described in the SO answer):
oldNumbers = [1,5,14,22,37]
newNumbers = [3,10,17,27,34,69]
allNumbers = oldNumbers:newNumbers
As you can see I attempted to add oldNumbers
to the head of newNumbers
with the intention of reversing it afterward (disregard that allNumbers
would be unorder for now, that's an exercise for another day).
As you probably guessed, it produced an error
error:
* Non type-variable argument in the constraint: Num [a]
(Use FlexibleContexts to permit this)
* When checking the inferred type
allNumbers :: forall a. (Num a, Num [a]) => [[a]]
So, as stated in the title, how would I efficiently merge two lists?
list haskell merge compiler-errors
|
show 2 more comments
I'm currently learning Haskell, and working with List
.
According to the HaskellWiki, if I wanted to merge two lists together, I would write:
list1 ++ list2
However, according to this answer, using ++ on a large list would be inefficient.
From researching, I came across this SO page, but that question requires a specific requirement for the output of the List
.
What I tried:
Suppose if I had two lists of numbers (for this example, assume that both lists are large enough that using ++
would be inefficient as described in the SO answer):
oldNumbers = [1,5,14,22,37]
newNumbers = [3,10,17,27,34,69]
allNumbers = oldNumbers:newNumbers
As you can see I attempted to add oldNumbers
to the head of newNumbers
with the intention of reversing it afterward (disregard that allNumbers
would be unorder for now, that's an exercise for another day).
As you probably guessed, it produced an error
error:
* Non type-variable argument in the constraint: Num [a]
(Use FlexibleContexts to permit this)
* When checking the inferred type
allNumbers :: forall a. (Num a, Num [a]) => [[a]]
So, as stated in the title, how would I efficiently merge two lists?
list haskell merge compiler-errors
2
(++)
is not inefficient in the sense that it works in linear time. The idea is that(++)
however is sometimes "misused" to append a single element to a list turning the algorithm in O(n^2) instead of O(n).
– Willem Van Onsem
Nov 17 '18 at 15:42
1
correctness first, efficiency later. really. -- so are you merging two sorted lists, and the merged list must be sorted as well? if not, there's absolutely nothing wrong with one-time++
. the answer you cite talks about repeated appending of one-element lists with++ [x]
being "bad".
– Will Ness
Nov 17 '18 at 15:47
@WillNess - The merged list doesn't have to be sorted. I'm taking small steps, so for now the mission is to merge the two lists. I'llsort
them later when I understandList
in Haskell better.
– user10641593
Nov 17 '18 at 15:55
then++
does the job. do you want to re-implement it, as an exercise? is your question about that ,or about the error you got?
– Will Ness
Nov 17 '18 at 15:55
1
Hey, that's my answer. I never said++
was inefficient.
– melpomene
Nov 17 '18 at 16:01
|
show 2 more comments
I'm currently learning Haskell, and working with List
.
According to the HaskellWiki, if I wanted to merge two lists together, I would write:
list1 ++ list2
However, according to this answer, using ++ on a large list would be inefficient.
From researching, I came across this SO page, but that question requires a specific requirement for the output of the List
.
What I tried:
Suppose if I had two lists of numbers (for this example, assume that both lists are large enough that using ++
would be inefficient as described in the SO answer):
oldNumbers = [1,5,14,22,37]
newNumbers = [3,10,17,27,34,69]
allNumbers = oldNumbers:newNumbers
As you can see I attempted to add oldNumbers
to the head of newNumbers
with the intention of reversing it afterward (disregard that allNumbers
would be unorder for now, that's an exercise for another day).
As you probably guessed, it produced an error
error:
* Non type-variable argument in the constraint: Num [a]
(Use FlexibleContexts to permit this)
* When checking the inferred type
allNumbers :: forall a. (Num a, Num [a]) => [[a]]
So, as stated in the title, how would I efficiently merge two lists?
list haskell merge compiler-errors
I'm currently learning Haskell, and working with List
.
According to the HaskellWiki, if I wanted to merge two lists together, I would write:
list1 ++ list2
However, according to this answer, using ++ on a large list would be inefficient.
From researching, I came across this SO page, but that question requires a specific requirement for the output of the List
.
What I tried:
Suppose if I had two lists of numbers (for this example, assume that both lists are large enough that using ++
would be inefficient as described in the SO answer):
oldNumbers = [1,5,14,22,37]
newNumbers = [3,10,17,27,34,69]
allNumbers = oldNumbers:newNumbers
As you can see I attempted to add oldNumbers
to the head of newNumbers
with the intention of reversing it afterward (disregard that allNumbers
would be unorder for now, that's an exercise for another day).
As you probably guessed, it produced an error
error:
* Non type-variable argument in the constraint: Num [a]
(Use FlexibleContexts to permit this)
* When checking the inferred type
allNumbers :: forall a. (Num a, Num [a]) => [[a]]
So, as stated in the title, how would I efficiently merge two lists?
list haskell merge compiler-errors
list haskell merge compiler-errors
edited Nov 23 '18 at 14:03
asked Nov 17 '18 at 15:40
user10641593
2
(++)
is not inefficient in the sense that it works in linear time. The idea is that(++)
however is sometimes "misused" to append a single element to a list turning the algorithm in O(n^2) instead of O(n).
– Willem Van Onsem
Nov 17 '18 at 15:42
1
correctness first, efficiency later. really. -- so are you merging two sorted lists, and the merged list must be sorted as well? if not, there's absolutely nothing wrong with one-time++
. the answer you cite talks about repeated appending of one-element lists with++ [x]
being "bad".
– Will Ness
Nov 17 '18 at 15:47
@WillNess - The merged list doesn't have to be sorted. I'm taking small steps, so for now the mission is to merge the two lists. I'llsort
them later when I understandList
in Haskell better.
– user10641593
Nov 17 '18 at 15:55
then++
does the job. do you want to re-implement it, as an exercise? is your question about that ,or about the error you got?
– Will Ness
Nov 17 '18 at 15:55
1
Hey, that's my answer. I never said++
was inefficient.
– melpomene
Nov 17 '18 at 16:01
|
show 2 more comments
2
(++)
is not inefficient in the sense that it works in linear time. The idea is that(++)
however is sometimes "misused" to append a single element to a list turning the algorithm in O(n^2) instead of O(n).
– Willem Van Onsem
Nov 17 '18 at 15:42
1
correctness first, efficiency later. really. -- so are you merging two sorted lists, and the merged list must be sorted as well? if not, there's absolutely nothing wrong with one-time++
. the answer you cite talks about repeated appending of one-element lists with++ [x]
being "bad".
– Will Ness
Nov 17 '18 at 15:47
@WillNess - The merged list doesn't have to be sorted. I'm taking small steps, so for now the mission is to merge the two lists. I'llsort
them later when I understandList
in Haskell better.
– user10641593
Nov 17 '18 at 15:55
then++
does the job. do you want to re-implement it, as an exercise? is your question about that ,or about the error you got?
– Will Ness
Nov 17 '18 at 15:55
1
Hey, that's my answer. I never said++
was inefficient.
– melpomene
Nov 17 '18 at 16:01
2
2
(++)
is not inefficient in the sense that it works in linear time. The idea is that (++)
however is sometimes "misused" to append a single element to a list turning the algorithm in O(n^2) instead of O(n).– Willem Van Onsem
Nov 17 '18 at 15:42
(++)
is not inefficient in the sense that it works in linear time. The idea is that (++)
however is sometimes "misused" to append a single element to a list turning the algorithm in O(n^2) instead of O(n).– Willem Van Onsem
Nov 17 '18 at 15:42
1
1
correctness first, efficiency later. really. -- so are you merging two sorted lists, and the merged list must be sorted as well? if not, there's absolutely nothing wrong with one-time
++
. the answer you cite talks about repeated appending of one-element lists with ++ [x]
being "bad".– Will Ness
Nov 17 '18 at 15:47
correctness first, efficiency later. really. -- so are you merging two sorted lists, and the merged list must be sorted as well? if not, there's absolutely nothing wrong with one-time
++
. the answer you cite talks about repeated appending of one-element lists with ++ [x]
being "bad".– Will Ness
Nov 17 '18 at 15:47
@WillNess - The merged list doesn't have to be sorted. I'm taking small steps, so for now the mission is to merge the two lists. I'll
sort
them later when I understand List
in Haskell better.– user10641593
Nov 17 '18 at 15:55
@WillNess - The merged list doesn't have to be sorted. I'm taking small steps, so for now the mission is to merge the two lists. I'll
sort
them later when I understand List
in Haskell better.– user10641593
Nov 17 '18 at 15:55
then
++
does the job. do you want to re-implement it, as an exercise? is your question about that ,or about the error you got?– Will Ness
Nov 17 '18 at 15:55
then
++
does the job. do you want to re-implement it, as an exercise? is your question about that ,or about the error you got?– Will Ness
Nov 17 '18 at 15:55
1
1
Hey, that's my answer. I never said
++
was inefficient.– melpomene
Nov 17 '18 at 16:01
Hey, that's my answer. I never said
++
was inefficient.– melpomene
Nov 17 '18 at 16:01
|
show 2 more comments
3 Answers
3
active
oldest
votes
According to the HaskellWiki, if I wanted to merge two lists together,
I would write:
list1 ++ list2
However, according to this answer, using
++
on a large list would be
inefficient.
I think you need to take the context into account in this answer. If we append two lists a
and b
with (++)
then it appends the two lists in O(m) (with m the length of the list). So this is, in terms of time complexity efficient. One can not construct such singly linked list more efficient than that.
@melpomene actually points to a popular mistake people new to Haskell make: they append a single element at the end of the list. Again if you only want to append a single element to the list, that is not a problem. This is a problem if you want to append n elements that way to a list, so if you each time append a single element to the list, and you do that n times, then the algorithm will be O(n2).
So in short, from a time complexity point of view, (++)
is not slow when you append two lists together, nor is it slow when you append a singleton list to it. There are however, in terms of asymptotic behavior, usually better ways than repeatedly appending a list with one element to a list, since then the first operand will typically become larger, and each iteration it takes O(n) time only to append a single element to a list. Typically one can use recursion on the tail element of a list in that case, or for example build the list in reverse.
(++)
is thus not "intrinsically" inefficient, by by using it in ways for which it was not design, you can obtain inefficient behavior.
An example where ++
will be quite slow is the following function that performs a "mapping":
badmap :: (a -> b) -> [a] -> [b]
badmap f = go
where go temp = temp
go temp (x:xs) = go (temp ++ [f x]) xs
There are two problems here:
- it is not lazy, it requires to evaluate the entire list before this can emit the first element; and
- it will run in quadratic time, since for each element in the input list, it will take more and more time to append this element.
A more effective way to implement a map is:
goodmap :: (a -> b) -> [a] -> [b]
goodmap f = go
where go (x:xs) = f x : go xs
go =
where does it say in the Report that lists are "singly linked"? I couldn't find anything like that there. The complexity of++
seems not to be specified either.
– Will Ness
Nov 17 '18 at 16:25
@WillNess: conceptually it is a sinly linked list, since there is no direct link in the data definition to the "parent". Furthermore that would also be strange, since one can reuse the tail, so there is no "previous". The time complexity follows from the implementation in the Haskell report on the standard prelude: haskell.org/onlinereport/standard-prelude.html
– Willem Van Onsem
Nov 17 '18 at 16:30
conceptually it could just as well be implemented on arrays with O(1) append. the implementation gives value semantics for the types / functions, not operational semantics / performance.
– Will Ness
Nov 17 '18 at 16:33
@WillNess: indeed, and then it is still O(n), O(n!),... Somehow this discussions feels a bit like the one I had with some friends about the first chapter of "Computational Complexity": "Why the computational model does not matter".
– Willem Van Onsem
Nov 17 '18 at 16:34
I really like this answer, but could you provide example code of append n elements that way to a list? It will help understand better of what not to do.
– user10641593
Nov 17 '18 at 23:21
add a comment |
There's absolutely nothing wrong with appending two lists with one-time ++
, however long they are.
The answer you cite, (rightfully) talks about repeated appending of one-element lists with ++ [x]
being "bad".
add a comment |
If you would like to efficiently append arbitrary lists, use a different data structure! Data.Seq is optimized for efficient appends, for example.
https://www.stackage.org/haddock/lts-12.19/containers-0.5.11.0/Data-Sequence.html#v:-62--60-
add a comment |
Your Answer
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53352740%2fefficiently-merge-two-lists%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
3 Answers
3
active
oldest
votes
3 Answers
3
active
oldest
votes
active
oldest
votes
active
oldest
votes
According to the HaskellWiki, if I wanted to merge two lists together,
I would write:
list1 ++ list2
However, according to this answer, using
++
on a large list would be
inefficient.
I think you need to take the context into account in this answer. If we append two lists a
and b
with (++)
then it appends the two lists in O(m) (with m the length of the list). So this is, in terms of time complexity efficient. One can not construct such singly linked list more efficient than that.
@melpomene actually points to a popular mistake people new to Haskell make: they append a single element at the end of the list. Again if you only want to append a single element to the list, that is not a problem. This is a problem if you want to append n elements that way to a list, so if you each time append a single element to the list, and you do that n times, then the algorithm will be O(n2).
So in short, from a time complexity point of view, (++)
is not slow when you append two lists together, nor is it slow when you append a singleton list to it. There are however, in terms of asymptotic behavior, usually better ways than repeatedly appending a list with one element to a list, since then the first operand will typically become larger, and each iteration it takes O(n) time only to append a single element to a list. Typically one can use recursion on the tail element of a list in that case, or for example build the list in reverse.
(++)
is thus not "intrinsically" inefficient, by by using it in ways for which it was not design, you can obtain inefficient behavior.
An example where ++
will be quite slow is the following function that performs a "mapping":
badmap :: (a -> b) -> [a] -> [b]
badmap f = go
where go temp = temp
go temp (x:xs) = go (temp ++ [f x]) xs
There are two problems here:
- it is not lazy, it requires to evaluate the entire list before this can emit the first element; and
- it will run in quadratic time, since for each element in the input list, it will take more and more time to append this element.
A more effective way to implement a map is:
goodmap :: (a -> b) -> [a] -> [b]
goodmap f = go
where go (x:xs) = f x : go xs
go =
where does it say in the Report that lists are "singly linked"? I couldn't find anything like that there. The complexity of++
seems not to be specified either.
– Will Ness
Nov 17 '18 at 16:25
@WillNess: conceptually it is a sinly linked list, since there is no direct link in the data definition to the "parent". Furthermore that would also be strange, since one can reuse the tail, so there is no "previous". The time complexity follows from the implementation in the Haskell report on the standard prelude: haskell.org/onlinereport/standard-prelude.html
– Willem Van Onsem
Nov 17 '18 at 16:30
conceptually it could just as well be implemented on arrays with O(1) append. the implementation gives value semantics for the types / functions, not operational semantics / performance.
– Will Ness
Nov 17 '18 at 16:33
@WillNess: indeed, and then it is still O(n), O(n!),... Somehow this discussions feels a bit like the one I had with some friends about the first chapter of "Computational Complexity": "Why the computational model does not matter".
– Willem Van Onsem
Nov 17 '18 at 16:34
I really like this answer, but could you provide example code of append n elements that way to a list? It will help understand better of what not to do.
– user10641593
Nov 17 '18 at 23:21
add a comment |
According to the HaskellWiki, if I wanted to merge two lists together,
I would write:
list1 ++ list2
However, according to this answer, using
++
on a large list would be
inefficient.
I think you need to take the context into account in this answer. If we append two lists a
and b
with (++)
then it appends the two lists in O(m) (with m the length of the list). So this is, in terms of time complexity efficient. One can not construct such singly linked list more efficient than that.
@melpomene actually points to a popular mistake people new to Haskell make: they append a single element at the end of the list. Again if you only want to append a single element to the list, that is not a problem. This is a problem if you want to append n elements that way to a list, so if you each time append a single element to the list, and you do that n times, then the algorithm will be O(n2).
So in short, from a time complexity point of view, (++)
is not slow when you append two lists together, nor is it slow when you append a singleton list to it. There are however, in terms of asymptotic behavior, usually better ways than repeatedly appending a list with one element to a list, since then the first operand will typically become larger, and each iteration it takes O(n) time only to append a single element to a list. Typically one can use recursion on the tail element of a list in that case, or for example build the list in reverse.
(++)
is thus not "intrinsically" inefficient, by by using it in ways for which it was not design, you can obtain inefficient behavior.
An example where ++
will be quite slow is the following function that performs a "mapping":
badmap :: (a -> b) -> [a] -> [b]
badmap f = go
where go temp = temp
go temp (x:xs) = go (temp ++ [f x]) xs
There are two problems here:
- it is not lazy, it requires to evaluate the entire list before this can emit the first element; and
- it will run in quadratic time, since for each element in the input list, it will take more and more time to append this element.
A more effective way to implement a map is:
goodmap :: (a -> b) -> [a] -> [b]
goodmap f = go
where go (x:xs) = f x : go xs
go =
where does it say in the Report that lists are "singly linked"? I couldn't find anything like that there. The complexity of++
seems not to be specified either.
– Will Ness
Nov 17 '18 at 16:25
@WillNess: conceptually it is a sinly linked list, since there is no direct link in the data definition to the "parent". Furthermore that would also be strange, since one can reuse the tail, so there is no "previous". The time complexity follows from the implementation in the Haskell report on the standard prelude: haskell.org/onlinereport/standard-prelude.html
– Willem Van Onsem
Nov 17 '18 at 16:30
conceptually it could just as well be implemented on arrays with O(1) append. the implementation gives value semantics for the types / functions, not operational semantics / performance.
– Will Ness
Nov 17 '18 at 16:33
@WillNess: indeed, and then it is still O(n), O(n!),... Somehow this discussions feels a bit like the one I had with some friends about the first chapter of "Computational Complexity": "Why the computational model does not matter".
– Willem Van Onsem
Nov 17 '18 at 16:34
I really like this answer, but could you provide example code of append n elements that way to a list? It will help understand better of what not to do.
– user10641593
Nov 17 '18 at 23:21
add a comment |
According to the HaskellWiki, if I wanted to merge two lists together,
I would write:
list1 ++ list2
However, according to this answer, using
++
on a large list would be
inefficient.
I think you need to take the context into account in this answer. If we append two lists a
and b
with (++)
then it appends the two lists in O(m) (with m the length of the list). So this is, in terms of time complexity efficient. One can not construct such singly linked list more efficient than that.
@melpomene actually points to a popular mistake people new to Haskell make: they append a single element at the end of the list. Again if you only want to append a single element to the list, that is not a problem. This is a problem if you want to append n elements that way to a list, so if you each time append a single element to the list, and you do that n times, then the algorithm will be O(n2).
So in short, from a time complexity point of view, (++)
is not slow when you append two lists together, nor is it slow when you append a singleton list to it. There are however, in terms of asymptotic behavior, usually better ways than repeatedly appending a list with one element to a list, since then the first operand will typically become larger, and each iteration it takes O(n) time only to append a single element to a list. Typically one can use recursion on the tail element of a list in that case, or for example build the list in reverse.
(++)
is thus not "intrinsically" inefficient, by by using it in ways for which it was not design, you can obtain inefficient behavior.
An example where ++
will be quite slow is the following function that performs a "mapping":
badmap :: (a -> b) -> [a] -> [b]
badmap f = go
where go temp = temp
go temp (x:xs) = go (temp ++ [f x]) xs
There are two problems here:
- it is not lazy, it requires to evaluate the entire list before this can emit the first element; and
- it will run in quadratic time, since for each element in the input list, it will take more and more time to append this element.
A more effective way to implement a map is:
goodmap :: (a -> b) -> [a] -> [b]
goodmap f = go
where go (x:xs) = f x : go xs
go =
According to the HaskellWiki, if I wanted to merge two lists together,
I would write:
list1 ++ list2
However, according to this answer, using
++
on a large list would be
inefficient.
I think you need to take the context into account in this answer. If we append two lists a
and b
with (++)
then it appends the two lists in O(m) (with m the length of the list). So this is, in terms of time complexity efficient. One can not construct such singly linked list more efficient than that.
@melpomene actually points to a popular mistake people new to Haskell make: they append a single element at the end of the list. Again if you only want to append a single element to the list, that is not a problem. This is a problem if you want to append n elements that way to a list, so if you each time append a single element to the list, and you do that n times, then the algorithm will be O(n2).
So in short, from a time complexity point of view, (++)
is not slow when you append two lists together, nor is it slow when you append a singleton list to it. There are however, in terms of asymptotic behavior, usually better ways than repeatedly appending a list with one element to a list, since then the first operand will typically become larger, and each iteration it takes O(n) time only to append a single element to a list. Typically one can use recursion on the tail element of a list in that case, or for example build the list in reverse.
(++)
is thus not "intrinsically" inefficient, by by using it in ways for which it was not design, you can obtain inefficient behavior.
An example where ++
will be quite slow is the following function that performs a "mapping":
badmap :: (a -> b) -> [a] -> [b]
badmap f = go
where go temp = temp
go temp (x:xs) = go (temp ++ [f x]) xs
There are two problems here:
- it is not lazy, it requires to evaluate the entire list before this can emit the first element; and
- it will run in quadratic time, since for each element in the input list, it will take more and more time to append this element.
A more effective way to implement a map is:
goodmap :: (a -> b) -> [a] -> [b]
goodmap f = go
where go (x:xs) = f x : go xs
go =
edited Nov 17 '18 at 23:31
answered Nov 17 '18 at 16:08
Willem Van OnsemWillem Van Onsem
148k16142232
148k16142232
where does it say in the Report that lists are "singly linked"? I couldn't find anything like that there. The complexity of++
seems not to be specified either.
– Will Ness
Nov 17 '18 at 16:25
@WillNess: conceptually it is a sinly linked list, since there is no direct link in the data definition to the "parent". Furthermore that would also be strange, since one can reuse the tail, so there is no "previous". The time complexity follows from the implementation in the Haskell report on the standard prelude: haskell.org/onlinereport/standard-prelude.html
– Willem Van Onsem
Nov 17 '18 at 16:30
conceptually it could just as well be implemented on arrays with O(1) append. the implementation gives value semantics for the types / functions, not operational semantics / performance.
– Will Ness
Nov 17 '18 at 16:33
@WillNess: indeed, and then it is still O(n), O(n!),... Somehow this discussions feels a bit like the one I had with some friends about the first chapter of "Computational Complexity": "Why the computational model does not matter".
– Willem Van Onsem
Nov 17 '18 at 16:34
I really like this answer, but could you provide example code of append n elements that way to a list? It will help understand better of what not to do.
– user10641593
Nov 17 '18 at 23:21
add a comment |
where does it say in the Report that lists are "singly linked"? I couldn't find anything like that there. The complexity of++
seems not to be specified either.
– Will Ness
Nov 17 '18 at 16:25
@WillNess: conceptually it is a sinly linked list, since there is no direct link in the data definition to the "parent". Furthermore that would also be strange, since one can reuse the tail, so there is no "previous". The time complexity follows from the implementation in the Haskell report on the standard prelude: haskell.org/onlinereport/standard-prelude.html
– Willem Van Onsem
Nov 17 '18 at 16:30
conceptually it could just as well be implemented on arrays with O(1) append. the implementation gives value semantics for the types / functions, not operational semantics / performance.
– Will Ness
Nov 17 '18 at 16:33
@WillNess: indeed, and then it is still O(n), O(n!),... Somehow this discussions feels a bit like the one I had with some friends about the first chapter of "Computational Complexity": "Why the computational model does not matter".
– Willem Van Onsem
Nov 17 '18 at 16:34
I really like this answer, but could you provide example code of append n elements that way to a list? It will help understand better of what not to do.
– user10641593
Nov 17 '18 at 23:21
where does it say in the Report that lists are "singly linked"? I couldn't find anything like that there. The complexity of
++
seems not to be specified either.– Will Ness
Nov 17 '18 at 16:25
where does it say in the Report that lists are "singly linked"? I couldn't find anything like that there. The complexity of
++
seems not to be specified either.– Will Ness
Nov 17 '18 at 16:25
@WillNess: conceptually it is a sinly linked list, since there is no direct link in the data definition to the "parent". Furthermore that would also be strange, since one can reuse the tail, so there is no "previous". The time complexity follows from the implementation in the Haskell report on the standard prelude: haskell.org/onlinereport/standard-prelude.html
– Willem Van Onsem
Nov 17 '18 at 16:30
@WillNess: conceptually it is a sinly linked list, since there is no direct link in the data definition to the "parent". Furthermore that would also be strange, since one can reuse the tail, so there is no "previous". The time complexity follows from the implementation in the Haskell report on the standard prelude: haskell.org/onlinereport/standard-prelude.html
– Willem Van Onsem
Nov 17 '18 at 16:30
conceptually it could just as well be implemented on arrays with O(1) append. the implementation gives value semantics for the types / functions, not operational semantics / performance.
– Will Ness
Nov 17 '18 at 16:33
conceptually it could just as well be implemented on arrays with O(1) append. the implementation gives value semantics for the types / functions, not operational semantics / performance.
– Will Ness
Nov 17 '18 at 16:33
@WillNess: indeed, and then it is still O(n), O(n!),... Somehow this discussions feels a bit like the one I had with some friends about the first chapter of "Computational Complexity": "Why the computational model does not matter".
– Willem Van Onsem
Nov 17 '18 at 16:34
@WillNess: indeed, and then it is still O(n), O(n!),... Somehow this discussions feels a bit like the one I had with some friends about the first chapter of "Computational Complexity": "Why the computational model does not matter".
– Willem Van Onsem
Nov 17 '18 at 16:34
I really like this answer, but could you provide example code of append n elements that way to a list? It will help understand better of what not to do.
– user10641593
Nov 17 '18 at 23:21
I really like this answer, but could you provide example code of append n elements that way to a list? It will help understand better of what not to do.
– user10641593
Nov 17 '18 at 23:21
add a comment |
There's absolutely nothing wrong with appending two lists with one-time ++
, however long they are.
The answer you cite, (rightfully) talks about repeated appending of one-element lists with ++ [x]
being "bad".
add a comment |
There's absolutely nothing wrong with appending two lists with one-time ++
, however long they are.
The answer you cite, (rightfully) talks about repeated appending of one-element lists with ++ [x]
being "bad".
add a comment |
There's absolutely nothing wrong with appending two lists with one-time ++
, however long they are.
The answer you cite, (rightfully) talks about repeated appending of one-element lists with ++ [x]
being "bad".
There's absolutely nothing wrong with appending two lists with one-time ++
, however long they are.
The answer you cite, (rightfully) talks about repeated appending of one-element lists with ++ [x]
being "bad".
answered Nov 17 '18 at 16:01
Will NessWill Ness
45.4k468124
45.4k468124
add a comment |
add a comment |
If you would like to efficiently append arbitrary lists, use a different data structure! Data.Seq is optimized for efficient appends, for example.
https://www.stackage.org/haddock/lts-12.19/containers-0.5.11.0/Data-Sequence.html#v:-62--60-
add a comment |
If you would like to efficiently append arbitrary lists, use a different data structure! Data.Seq is optimized for efficient appends, for example.
https://www.stackage.org/haddock/lts-12.19/containers-0.5.11.0/Data-Sequence.html#v:-62--60-
add a comment |
If you would like to efficiently append arbitrary lists, use a different data structure! Data.Seq is optimized for efficient appends, for example.
https://www.stackage.org/haddock/lts-12.19/containers-0.5.11.0/Data-Sequence.html#v:-62--60-
If you would like to efficiently append arbitrary lists, use a different data structure! Data.Seq is optimized for efficient appends, for example.
https://www.stackage.org/haddock/lts-12.19/containers-0.5.11.0/Data-Sequence.html#v:-62--60-
answered Nov 23 '18 at 14:49
Dan BurtonDan Burton
37.5k2098179
37.5k2098179
add a comment |
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53352740%2fefficiently-merge-two-lists%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
2
(++)
is not inefficient in the sense that it works in linear time. The idea is that(++)
however is sometimes "misused" to append a single element to a list turning the algorithm in O(n^2) instead of O(n).– Willem Van Onsem
Nov 17 '18 at 15:42
1
correctness first, efficiency later. really. -- so are you merging two sorted lists, and the merged list must be sorted as well? if not, there's absolutely nothing wrong with one-time
++
. the answer you cite talks about repeated appending of one-element lists with++ [x]
being "bad".– Will Ness
Nov 17 '18 at 15:47
@WillNess - The merged list doesn't have to be sorted. I'm taking small steps, so for now the mission is to merge the two lists. I'll
sort
them later when I understandList
in Haskell better.– user10641593
Nov 17 '18 at 15:55
then
++
does the job. do you want to re-implement it, as an exercise? is your question about that ,or about the error you got?– Will Ness
Nov 17 '18 at 15:55
1
Hey, that's my answer. I never said
++
was inefficient.– melpomene
Nov 17 '18 at 16:01