检查并查看列表的所有元素是否与参数匹配

时间:2017-05-09 19:38:48

标签: haskell

我想创建一个函数,检查Bert Bos puzzle的每一行的每一行是否一次红色,但从概念上讲,我很难用这个。最初我使用所有蓝色方块制作电路板,但是一旦使用翻转功能翻转方块,allRed功能应该能够判断该行是否全部为红色。每行由颜色列表表示,蓝色或红色

我知道我应该使用all函数,但是我遇到了一些问题,实际上是根据我的情况编写的

这是我到目前为止所做的:

generateboard :: Int -> [[Color]]
generateboard n = replicate n (replicate n Blue)


allRed :: [[Color]] -> Bool
let board = generateboard
allRed board = []
allRed board = all ([x:_ | x <- board, x == Red]) 
  allRed board 

2 个答案:

答案 0 :(得分:1)

这里有许多错误和误解。我建议您阅读introductory Haskell materials中的任何内容,以加强您对该语言的基本理解。我会直接回答这个问题。

generateboard看起来很棒。

您认为all :: Foldable t => (a -> Bool) -> t a -> Bool将帮助我们定义allRed是正确的。如果类型令人困惑,您可以将其视为(a -> Bool) -> [a] -> BoolThe documentation says

  

确定[list]的所有元素是否满足谓词。

要使用all,我们需要一个类型为a -> Bool的谓词(一个函数)和一个类型为[a]的列表。我们知道谓词需要是什么:

\x -> x == Red

另一种写这个的方法是:

(==) Red

谓词的类型为Color -> Bool,因此我们的列表必须具有类型[Color]。但是,我们有一个[[Color]]类型的列表。我可以通过两种方式来解决这个问题。

更简单的想法是观察如果我们关心的是细胞,那么电路板结构是无关紧要的。因此,我们可以使用concat :: [[a]] -> [a]展平结构。那么我们的解决方案是:

allRed xs = all ((==) Red) (concat xs)

还写了:

allRed = all ((==) Red) . concat

另一个解决方案是观察如果所有行都是红色,那么整个板必须是红色的。这个解决方案是:

allRed xs = all (all ((==) Red)) xs

还写了:

allRed = all (all ((==) Red))

答案 1 :(得分:1)

首先,all功能:

all :: (a -> Bool) -> [a] -> Bool
all p xs = ...

获取表示属性和列表p的函数xs,并测试p x是否为真(即,如果x具有属性px的每个元素xs。 (例如,all even [2,4,7]检查给定列表的所有元素是否均匀,并返回False,因为even 7等于False。)因此,使用{{1}你需要两个参数 - 要检查的项目列表,以及检查一个项目的函数。

第二,当面临在Haskell中处理数据结构的问题时(在这种情况下为all),一个很好的经验法则是从外部解构结构,每个级别使用一个函数结构你有(内部)颜色列表的(外部)列表,所以从外部列表,行列表开始。

如何编写一个函数来检查 all 外部列表中的行是否满足它们只包含红色的属性&#34;?或者,更简单地说,如果你已经有一个辅助函数[[Color]]表示只有红色的行的属性,你会如何使用all编写这个函数?

redRow

如果您可以使用redRow :: [Color] -> Bool redRow row = ... allRed boardall撰写board,那么您已经将问题缩小为编写{{1}的定义},它使用更简单的数据结构,(内部)颜色列表。

要写redRow,您同样应该能够再次使用redRow表示颜色属性为红色的函数:

redRow

(或使用等效的lambda或&#34;部分&#34;直接)。

在这种情况下,另一种方法也是可行的 - 您可以使用all来&#34;展平&#34;将外部列表和内部列表放在一起,然后解决检查大型长列表中的所有颜色是否为红色的更简单问题。