我在Haskell中有一个2D列表[[Int]]
,我想检查两件事:
例如:
[[1,2,3], [1,55,9]]
具有与列相同的行数 - 此处为2 - 并且每行具有相同数量的元素,即3。
但是
[[1,2], [1,55], [4,7]]
每行中的元素数量相同,但行数和列数不等,即3r 2c。
又一个例子:
[[1,2], [1,55], [4,7,8]]
既没有与列相同的行数,也没有每行具有相同数量的元素。
实际上,第1步包括第2步,我是对吗?
我的尝试:
所以我到目前为止所尝试的是:
listIsEqual :: [[Int]] -> Bool
listIsEqual myList = (all (\x -> length x == (length myList)) )
现在我收到以下错误消息:
Couldn't match expected type `Bool' with actual type `[a0] -> Bool'
In the return type of a call of `all'
Probable cause: `all' is applied to too few arguments
In the expression: (all (\ x -> length x == (length myList)))
In an equation for `listIsEqual':
listIsEqual myList = (all (\ x -> length x == (length myList)))
有人能告诉我问题在哪里吗?
还有其他方法可以解决这个问题吗?
答案 0 :(得分:6)
GHC的错误消息并不总是最有帮助的,但在这种情况下它是正确的。
可能原因:“全部”适用于太少的参数
事实上,你忘记了all
的第二个论点:
listIsEqual myList = all (\x -> length x == length myList) myList
^^^^^^
答案 1 :(得分:3)
对于第二个任务,您可以映射定义函数的每一行的长度(该行中的列数)
let columnLengths rows = map length rows
Prelude> columnLengths [[1,2], [1,55], [4,7,8]]
[2,2,3]
现在我们有一个包含列长度的列表,我们必须检查它们是否全部相等。 nub
中的Data.List
函数会从列表中删除重复项。
let columnsLengthEqual = (==) 1 . length . nub . columnLengths
或者一起
let columnsLengthEqual = (==) 1 . length . nub . map length
答案 2 :(得分:0)
矩阵遵循您的标准,是矩阵矩阵,然后检查第一行的长度的平方是否等于元素的数量应该没问题。
isSquaredMatrix xs@(h:_) = ((^2) . length $ h) == (length . concat $ xs)
isSquaredMatrix _ = True
但正如哈马尔所指出的那样,这是错误的,因为我们可以使用错误的输入获得积极的结果。
# isSquaredMatrix [[1,2,3],[4,5],[6,7,8,9]]
True -- But this is false
@John,
当我们想要在分解时同时引用整个类型时,我们使用@
进行模式匹配。一个例子可以给你更多的见解,
通常我们可以使用模式匹配来定义在列表上工作的详尽函数,如下所示。
actOnList [] = -- do something when we encounter an empty list
actOnList (x:xs) = -- do something with h, and do another stuff with xs
例如,
actOnList [] = []
actOnList (x:xs) =
if (pred x)
then x:xs
else actOnList xs
这里我的函数完成了列表,直到满足谓词 我们可以想象skipUntilMeetAChar
skipUntilMeetAChar :: [Char] -> Char -> [Char]
skipUntilMeetAChar [] c = []
skipUntilMeetAChar (x:xs) c =
if (x==c)
then x:xs
else actOnList xs c
正如您所看到的那样,我们希望返回列表,而不仅仅是尾部,然后我们需要使用头部x
和尾部{{}来重建列表。 1}}。这可以使用xs
来克服。
@
现在,关于($)运算符,这又是一些语法糖 由于函数应用程序是左关联的,这导致我们广泛使用括号来重新排序函数的应用程序,如下例所示。
skipUntilMeetAChar :: String -> Char -> String
skipUntilMeetAChar [] c = []
skipUntilMeetAChar l@(x:xs) c =
if (x==c)
then l
else actOnList xs c
然后为了避免管理结束括号的痛苦,引入了美元运算符# f3 (f2 (f1 (f0 x)))
,然后我们之前的表达式变为。
$
这绝对是更易读和最容易编写的。
注意此运算符定义如下。
# f3 $ f2 $ f1 $ f0 x
我建议您在咨询以下introduction material时了解更多信息。