Haskell - 检查2D列表是否与列具有相同的行数

时间:2013-05-07 10:12:06

标签: arrays list haskell equality

我在Haskell中有一个2D列表[[Int]],我想检查两件事:

  1. 列表是否将行数作为列
  2. 行是否具有sam数量的元素
  3. 例如:

    [[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)))
    

    有人能告诉我问题在哪里吗?

    还有其他方法可以解决这个问题吗?

3 个答案:

答案 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时了解更多信息。