Efficiently merge two lists












2















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?










share|improve this question




















  • 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 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








  • 1





    Hey, that's my answer. I never said ++ was inefficient.

    – melpomene
    Nov 17 '18 at 16:01
















2















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?










share|improve this question




















  • 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 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








  • 1





    Hey, that's my answer. I never said ++ was inefficient.

    – melpomene
    Nov 17 '18 at 16:01














2












2








2








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?










share|improve this question
















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






share|improve this question















share|improve this question













share|improve this question




share|improve this question








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'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








  • 1





    Hey, that's my answer. I never said ++ was inefficient.

    – melpomene
    Nov 17 '18 at 16:01














  • 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 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








  • 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












3 Answers
3






active

oldest

votes


















6















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:




  1. it is not lazy, it requires to evaluate the entire list before this can emit the first element; and

  2. 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 =





share|improve this answer


























  • 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



















4














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".






share|improve this answer































    0














    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-






    share|improve this answer























      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
      });


      }
      });














      draft saved

      draft discarded


















      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









      6















      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:




      1. it is not lazy, it requires to evaluate the entire list before this can emit the first element; and

      2. 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 =





      share|improve this answer


























      • 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
















      6















      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:




      1. it is not lazy, it requires to evaluate the entire list before this can emit the first element; and

      2. 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 =





      share|improve this answer


























      • 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














      6












      6








      6








      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:




      1. it is not lazy, it requires to evaluate the entire list before this can emit the first element; and

      2. 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 =





      share|improve this answer
















      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:




      1. it is not lazy, it requires to evaluate the entire list before this can emit the first element; and

      2. 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 =






      share|improve this answer














      share|improve this answer



      share|improve this answer








      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



















      • 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













      4














      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".






      share|improve this answer




























        4














        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".






        share|improve this answer


























          4












          4








          4







          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".






          share|improve this answer













          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".







          share|improve this answer












          share|improve this answer



          share|improve this answer










          answered Nov 17 '18 at 16:01









          Will NessWill Ness

          45.4k468124




          45.4k468124























              0














              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-






              share|improve this answer




























                0














                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-






                share|improve this answer


























                  0












                  0








                  0







                  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-






                  share|improve this answer













                  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-







                  share|improve this answer












                  share|improve this answer



                  share|improve this answer










                  answered Nov 23 '18 at 14:49









                  Dan BurtonDan Burton

                  37.5k2098179




                  37.5k2098179






























                      draft saved

                      draft discarded




















































                      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.




                      draft saved


                      draft discarded














                      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





















































                      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







                      Popular posts from this blog

                      Wiesbaden

                      Marschland

                      Dieringhausen