I have a task, where I am stuck at a point, where I do not get any further. Given is a function:
transpose :: [[a]] -> [[a]]
transpose [] = []
transpose ([]:ls) = transpose ls
transpose ll = [h | (h:_) <- ll] : transpose [t |(_:t) <- ll]
I shall write it again using the do-notation on the one hand and the bind-operator on the other hand. I may use hd, tl and (:). I do not have problems with the do-notation solution but there is a pattern matching problem with the bind version. Here is, what I have so far:
transheadA ll = ll >>= \(h:_) ->
return h
transtailA ll = ll >>= \(_:t) ->
return t
transposeA :: [[a]] -> [[a]]
transposeA [] = []
transposeA ([]:ls) = transposeA ls
transposeA ll = (transheadA ll : transposeA (transtailA ll))
The same style for the do-notation works but with the bind operator I get a pattern match error at transheadA with
\(h:_) -> ...
See:
transposeA [[1,2,3],[4,5,6],[7,8]]
[[1,4,7],[2,5,8],[3,6*** Exception: transpose.hs:(16,22)-(17,24): Non-exhaustive patterns in lambda
I was thinking about how to solve this problem a longer time but I do not know, where to add a new pattern to let this work.
EDIT
I just want hints, of course. Direct solutions are not the sense of the homework nor of this board. Thank You
EDIT SOLUTION
Thanks to CommuSoft I could solve this problem, I think. My solution now is the following:
transheadA :: [[a]] -> [a]
transheadA ll = ll >>= f
where f (h:_) = return h
f _ = fail []
transtailA :: [[a]] -> [[a]]
transtailA ll = ll >>= f
where f (_:t) = return t
f _ = fail []
transposeA :: [[a]] -> [[a]]
transposeA [] = []
transposeA ([]:ls) = transposeA ls
transposeA ll = (transheadA ll : transposeA (transtailA ll))
There are a few problems with this approach:
The signature of
transheadA
should be different than the one fortranstailA
.Since you do some pattern matching in the list comprehension, you cannot simply use this in the lambda expression: it is possible the pattern fails in which case that part of the list comprehension
fail
s as well. You can inline this as:Then you can use
f
in the side of the binding operator>>=
. Clearly this has an impact on how to encode things. Implicitly for each such pattern matching (thus everything notx <-
withx
a single variable) Haskell could have written suchfail
(be aware Haskell does not necessarily uses the list monad).As you can read here for the list monad, you don't need to use
return
, although in this context it not much of a problem, but will reduce the length of your code. In that case you need to replace the right hand side of the expression with[x]
instead ofx
.Based on the above hints, I've managed to fix your implementation of
transpose
myself. I hope this clarifies a thing or two?