我有一项任务,我被困在某个地方,在那里我没有得到任何进一步的帮助。 给定是一个函数:
transpose :: [[a]] -> [[a]]
transpose [] = []
transpose ([]:ls) = transpose ls
transpose ll = [h | (h:_) <- ll] : transpose [t |(_:t) <- ll]
我将一方面使用do-notation和另一方面使用bind-operator再次编写它。我可以使用hd,tl和(:)。 我没有使用do-notation解决方案的问题,但是绑定版本存在模式匹配问题。 这是我到目前为止所做的:
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))
与do-notation相同的样式有效但是使用bind运算符我在transheadA上得到了一个模式匹配错误
\(h:_) -> ...
请参阅:
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
我在考虑如何更长时间地解决这个问题,但我不知道,在哪里添加新模式让这个工作。
我当然想要提示。 直接解决方案不是家庭作业和董事会的意义。 谢谢
感谢CommuSoft我能解决这个问题。 我现在的解决方案如下:
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))
答案 0 :(得分:3)
这种方法存在一些问题:
transheadA
的签名应与transtailA
的签名不同。
transheadA :: [[a]] -> [a]
transtailA :: [[a]] -> [[a]]
由于你在列表推导中做了一些模式匹配,你不能简单地在lambda表达式中使用它:模式可能会失败,在这种情况下,列表推导部分fail
也是如此。您可以将其内联为:
where f (h:_) = return h
f _ = fail []
然后,您可以在绑定运算符f
的一侧使用>>=
。显然,这会对如何编码事物产生影响。隐式地为每个这样的模式匹配(因此一切都不是x <-
和x
单个变量)Haskell可以编写这样的fail
(注意Haskell不一定使用列表monad)。
正如您可以阅读here列表monad,您不需要使用return
,虽然在这种情况下它没有太大的问题,但会减少长度你的代码。在这种情况下,您需要将表达式的右侧替换为[x]
而不是x
。
根据以上提示,我已设法自行修复transpose
的实施。我希望这澄清一两件事?