-2

add_lists list1 list2: returns the sum of the elements in the same position in each list as a new list. If one list is shorter than the other, assume that the shorter list has zero’s in the “missing places”. This is my haskell code :

add_lists list1 list2= if length.list1 < length.list2
                       then list2 ++ [i] && zipWith(+)list1 list2 
                       else zipWith (+) list1 list2
                       where [i|i=0,i=length.list2-length.list1]

I keep getting errors

  • 1
    Hint: make use of *explicit recursion*. – Willem Van Onsem Jun 07 '21 at 22:15
  • voting to close due to lack of focus. https://stackoverflow.com/help/how-to-ask –  Jun 07 '21 at 23:00
  • Your syntax is wrong. `length . list1` would compose the `length` function with a `list1` function, but `list1` isn't a function. I don't know what your `where` clause is supposed to be doing, but that's for binding a variable. And you have what looks like a list comprehension in there, but the syntax is all bogus. I can't make heads or tails of it. – dfeuer Jun 07 '21 at 23:21
  • @dfeuer: Read it “word-for-word”. `length.list1` = “length **of** `list1`”, as in `head . reverse` = “head of reverse (of a list)”; `list2 ++ [i]` = “to `list2`, **append** (by mutation) **the list** `i`”; `&&` = “**and** (then)”; and `[i|i=0,i=length.list2-length.list1]` is “**the list** `i` (again interpreting `[]` as a sigil) is **equal** to 0 (everywhere) and `i` **is** (in the sense of ‘has’) the length **of** `list2` minus the length **of** `list1`”. – Jon Purdy Jun 08 '21 at 00:33
  • @JonPurdy, I don't think I'm able to stretch my mind far enough to understand all these mistakes, sorry. – dfeuer Jun 08 '21 at 04:27
  • 1
    You can create point-wise versions of functions on lists defining a combinator `pw f = map f . transpose` (where `transpose` is from `Data.List`). So for this case you can define a more general `sumPW = pw sum` which operates on lists of lists. Then `add_lists list1 list2 = sumPW [list1, list2]`. – peter pun Jun 08 '21 at 11:23
  • @peterpun more like column-wise. :) nice! your `pw` is so short it's better to just write it out, `foo xs ys = map sum $ transpose [xs,ys]` (unless you use it a lot). cf. [this use](https://stackoverflow.com/a/54970785/849891) of `transpose` for a similar purpose. – Will Ness Jun 09 '21 at 14:55
  • @WillNess Yes, usually the term "point-wise" is used when the inputs and output are functions. This one is like a version of "component-wise" for lists. Notice the similarity to `cotraverse f = fmap f . distribute` from `Data.Distributive` which generalizes "point/component-wise". – peter pun Jun 10 '21 at 21:10
  • (`transpose` can be defined as ``takeWhile (not . null) . map catMaybes . F.toList . distribute . (map $ (`SI.prepend` pure Nothing) . map Just)``, where `F` is `Data.Foldable` and `SI` is `Data.Stream.Infinite`, going from `[[a]]` to `[Stream (Maybe a)]`, then via `distribute` to `Stream [Maybe a]` and finally back to `[[a]]`) – peter pun Jun 10 '21 at 21:10
  • @peterpun thanks, I'll have to work through that one. :) – Will Ness Jun 11 '21 at 07:31

3 Answers3

2

It's probably easiest to use explicit recursion here.

add_lists [] list2 = list2
add_lists list1 [] = list1
add_lists (x:xs) (y:ys) = x + y : add_lists xs ys
Mark Saving
  • 1,752
  • 7
  • 11
1

Syntactically

  1. the . in length.list2 is a function composition operator while list2 is no function,
  2. where i= would start a definition while where [i| does not,
  3. an i= within a list comprehension wants a let i= or i<-, and
  4. your && can only combine two Bool values.

You want to work around the shortening zipWith

a +++ b = zipWith (+) a b ++ drop (length b) a ++ drop (length a) b

or build a less discarding zipWith alternative:

(a:c) +++ (b:d) = (a+b) : (c +++ d)
e +++ [] = e
[] +++ f = f
Roman Czyborra
  • 127
  • 1
  • 4
  • `length` is usually considered problematic, since it doesn't work on infinite lists and has performance (memory) impact in general. – Will Ness Jun 09 '21 at 15:00
1

Using the semialign package, you can write this:

import Data.Align (padZipWith)
import Data.Maybe (fromMaybe)

addLists :: (Semialign t, Num a) => t a -> t a -> t a
addLists = padZipWith (\a b => fromMaybe 0 a + fromMaybe 0 b)
dfeuer
  • 48,079
  • 5
  • 63
  • 167