Haskell 绑定运算符的模式匹配错误
Haskell pattern match error with bind operator
我有一个任务,我被困在一个点上,我无法继续前进。
给出的是一个函数:
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 的相同样式有效,但使用绑定运算符时,我在 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))
这种方法存在一些问题:
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 for the list monad,你不需要使用 return
,虽然在这种情况下它不是什么大问题,但是会减少代码的长度。在这种情况下,您需要将表达式的右侧替换为 [x]
而不是 x
.
根据以上提示,我已经设法自行修复了 transpose
的实现。我希望这能澄清一两件事?
我有一个任务,我被困在一个点上,我无法继续前进。 给出的是一个函数:
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 的相同样式有效,但使用绑定运算符时,我在 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))
这种方法存在一些问题:
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 for the list monad,你不需要使用
return
,虽然在这种情况下它不是什么大问题,但是会减少代码的长度。在这种情况下,您需要将表达式的右侧替换为[x]
而不是x
.
根据以上提示,我已经设法自行修复了 transpose
的实现。我希望这能澄清一两件事?