我想创建一个函数,检查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
答案 0 :(得分:1)
这里有许多错误和误解。我建议您阅读introductory Haskell materials中的任何内容,以加强您对该语言的基本理解。我会直接回答这个问题。
generateboard
看起来很棒。
您认为all :: Foldable t => (a -> Bool) -> t a -> Bool
将帮助我们定义allRed
是正确的。如果类型令人困惑,您可以将其视为(a -> Bool) -> [a] -> Bool
。 The 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
具有属性p
) x
的每个元素xs
。 (例如,all even [2,4,7]
检查给定列表的所有元素是否均匀,并返回False
,因为even 7
等于False
。)因此,使用{{1}你需要两个参数 - 要检查的项目列表,以及检查一个项目的函数。
第二,当面临在Haskell中处理数据结构的问题时(在这种情况下为all
),一个很好的经验法则是从外部解构结构,每个级别使用一个函数结构你有(内部)颜色列表的(外部)列表,所以从外部列表,行列表开始。
如何编写一个函数来检查 all 外部列表中的行是否满足它们只包含红色的属性&#34;?或者,更简单地说,如果你已经有一个辅助函数[[Color]]
表示只有红色的行的属性,你会如何使用all
编写这个函数?
redRow
如果您可以使用redRow :: [Color] -> Bool
redRow row = ...
,allRed board
和all
撰写board
,那么您已经将问题缩小为编写{{1}的定义},它使用更简单的数据结构,(内部)颜色列表。
要写redRow
,您同样应该能够再次使用redRow
表示颜色属性为红色的函数:
redRow
(或使用等效的lambda或&#34;部分&#34;直接)。
在这种情况下,另一种方法也是可行的 - 您可以使用all
来&#34;展平&#34;将外部列表和内部列表放在一起,然后解决检查大型长列表中的所有颜色是否为红色的更简单问题。