0

我正在尝试在 haskell 中创建一个函数,以了解列表列表中的所有元素是否具有相同的长度。(我在以前的帖子中搜索过答案,但没有一个有效)。

sameLength :: [[t]] -> String
sameLength [] = "Empty list"
sameLength [[items]]
    | and $ map (\x -> length x == (length $ head [[items]])) [[items]] = "Same length"
    | otherwise = "Not the same length"

问题是它不起作用:

*Main> :l test.hs
[1 of 1] Compiling Main             ( test.hs, interpreted )
Ok, modules loaded: Main.
*Main> sameLength []
"Empty list"
*Main> sameLength [[1,2],[3,4]]
"*** Exception: test.hs:(2,1)-(5,39): Non-exhaustive patterns in function sameLength

*Main> sameLength [[1,2]]
"*** Exception: test.hs:(2,1)-(5,39): Non-exhaustive patterns in function sameLength

我真的不明白问题出在哪里。它处理参数是空列表和不是空列表的情况。我错了吗 ?我错过了什么 ?

谢谢你的帮助 :)

4

2 回答 2

4

该模式[x]匹配一​​个只包含一个项目的列表,x。因此,该模式[[items]]匹配包含单个项目的单个列表。您想要的是在第二种情况下匹配所有非空列表。但是由于已经匹配了空列表,因此通过消除您只想匹配尚未匹配的任何内容。

sameLength :: [[t]] -> String
sameLength [] = "Empty list"
sameLength items = -- Code here
于 2015-03-28T13:06:48.110 回答
3

你这里太多了[..]

sameLength [[items]] 

(正如西尔维奥解释得很好) - 尝试

sameLength items 

反而。

此外a == a,您不必检查头部的长度是否与头部的长度相同(当然),因此我建议您执行以下操作:

sameLength :: [[a]] -> Bool
sameLength []     = True
sameLength (h:tl) = all ((length h ==) . length) tl

因为我认为Bool结果更加有用和自然

这是如何运作的?

all接受一个谓词和一个列表,并检查谓词是否适用于列表的每个元素 -(length h ==) . length = \xs -> length h == length xs作为谓词检查给定列表xs是否与头列表具有相同的长度h- 所以由于上面的注释,您只需要检查这个与尾列表tl

评论

您可以争论空列表的所有元素是否应该具有相同的长度- 但我认为答案应该是肯定的;)

例子

Prelude> sameLength [[1,2],[3,4]]
True
Prelude> sameLength [[1,2],[3,4,5]]
False
Prelude> sameLength [[1,2]]
True
Prelude> sameLength []
True

如果您担心性能

(或者你不喜欢无点风格)

sameLength :: [[a]] -> Bool
sameLength []     = True
sameLength (h:tl) = let l = length h
                    in all (\xs -> length xs == l) tl
于 2015-03-28T13:11:25.827 回答