1

While I understand that there may be transpose or ZipList functions in Haskell, I am trying to build my own transpose function that will take n lists of equal length m and transpose them into m lists of length n.

So far I have the function nearly working with the following code:

list = [[1,2,3],[4,5,6],[7,8,9]]

head' (x:xs) = x

head'' [] = []
head'' (xs:lxs) = head' xs:head'' lxs

tail' [] = []
tail' (x:xs) = xs

tail'' [] = []
tail'' (xs:lxs) = tail' xs:tail'' lxs

merge (xs:lxs) = (head' xs:head'' lxs):(merge (tail' xs:tail'' lxs))

and I get the following output when I run > merge list in ghci I get:

[[1,4,7],[2,5,8],[3,6,9],[*** Exception: list2.hs:16:1-16: Non-exhaustive patterns in function head'

which I am pretty sure means that the base case of the empty list on my head' function is missing. The list is transposed, just not closed. How do I deal with that problem in this case? I have an inkling that it might have to do with Maybe, but I'm having trouble implementing it that way.

Will Ness
  • 70,110
  • 9
  • 98
  • 181
Ron F
  • 37
  • 6
  • 6
    `head' (x:xs) = x`, but what is `head' []`? – Adam Smith Jan 04 '19 at 09:14
  • 1
    Since `head' xs:head'' lxs = head'' (xs:lxs)`, you can collapse `merge (xs:lxs) = (head' xs:head'' lxs):...` to `merge (xs:lxs) = (head'' (xs:lxs)):...`. Similar equational reasoning applies to the `...`, giving `merge (xs:lxs) = (head'' (xs:lxs)):(tail'' (xs:lxs))`. At that point there's not much point to pattern matching; `merge lxs = head'' lxs:tail'' lxs`. But now you should definitely be suspicious: this definition of `merge` obviously always calls `(:)` and never `[]`. So how does one get to the "end" of the `merge`'s output? – Daniel Wagner Jan 04 '19 at 18:13

2 Answers2

1

You need to add exit conditions:

merge [] = []
merge ([]:xss) = merge xss
talex
  • 17,973
  • 3
  • 29
  • 66
  • So when does `merge ([]:xss) = merge xss` run as opposed to the other two definitions of `merge`? – Ron F Jan 04 '19 at 18:24
0

map is all you need, in addition to the existing head and tail functions. For simplicity, this assumes that the input is always a non-empty list (i.e., xs might be [[],[],[]], but never [] alone, so there's no problem with using head or tail.)

> map head list
[1,4,7]
> map tail list
[[2,3],[5,6],[8,9]]
> let foo xs = if null (head xs) then [] else map head xs : foo (map tail xs)
> foo list
[[1,4,7],[2,5,8],[3,6,9]]
chepner
  • 497,756
  • 71
  • 530
  • 681