嗨,我是Haskell的新手,我有点失落。我已经得到了这个,但无法解决这个问题。
仅使用foldr
,布尔操作(||)
和False
定义一个函数
or_list :: [Bool] -> Bool
这样
or_list [b1, b2,...,bn] = b1 || b2 ||...|| bn
请注意
or_list [] = False
我想出了类似的东西
or_list :: [Bool] -> Bool
or_list [0..n] = foldr False (||) [0..n]
但是我真的不知道foldr
是如何运作的。如果有人能指出我走正确的道路,那将是一个很大的帮助。
答案 0 :(得分:11)
你几乎得到了正确的定义,但你的语法有点偏。你不能像
这样的模式匹配or_list [0..n] = ...
这只是无效的语法。事实上,你根本不需要模式匹配,你可以做到
or_list bs = foldr False (||) bs
通过查看foldr
的类型可以揭示下一个问题:
foldr :: (Bool -> Bool -> Bool) -> Bool -> [Bool] -> Bool
-- Simplified from its more general type
请注意,它的第一个参数是一个带有两个布尔值的函数,第二个参数只是一个布尔值。
foldr False (||) bs
但False
不是函数,(||)
不是布尔值。如果你交换它们就会得到
foldr (||) False bs
然后你的定义是正确的!
这是如何工作的?折叠是简单递归的推广,通常你有一个函数,你正在应用一个也取决于最后计算的值的参数。这些类型的递归对于将值列表转换为单个值非常有用。 foldr
的定义非常简单,我认为它有助于解释折叠如何工作
foldr f initial [] = initial
foldr f initial (x:xs) = f x (foldr f initial xs)
因此,如果我们要插入一些值并展开它
foldr (||) False [False, False, True]
= False || (foldr (||) False [False, True])
= False || (False || (foldr (||) False [True]))
= False || (False || (True || (foldr (||) False [])))
= False || (False || (True || (False)))
= False || (False || True)
= False || True
= True
另一种看待它的方法是它在列表中用:
替换f
和[]
initial
,所以如果你有
False : False : True : []
您向其foldr (||) False
申请,您将:
替换||
,[]
替换为False
,关联权利{{1} {}}}的一部分,所以
r
这与我们上面的扩展相同。 foldr
在相反的关联中起作用,因此False || (False || (True || (False)))
看起来像
foldl
因此,差异基本上是初始值停留在何处以及括号所在的位置。
答案 1 :(得分:2)
Prelude中的foldr
函数是一个高阶函数,它接受f
类型的函数(a -> b -> b)
并将其应用于类型[a]
的列表,从而产生类型列表[b]
。它还需要一个应用于z
f
象征性地在伪代码中这样减少:
foldr f z [a,b,c,...,n] == f a (f b (f c (... (f n z)...)))
所以对于你的功能,你需要这样的东西:
foldr (||) False [a,b,c,...,n] = a || (b || (c ... (n || False)))
希望有助于直觉的折叠。
答案 2 :(得分:0)
您有以下定义:
or_list :: [Bool] -> Bool
右。
让我们看看第二行:
or_list [0..n] = foldr False (||) [0..n]
所以实际上这非常接近所需,但有几个问题。首先让我们来看看:
or_list [0..n] = ...
这可能应该是这样的:
or_list (x:xs) = ...
请参阅this了解原因。接下来,我会给你一些提示。密切注意foldr
的签名,你没有给出正确的参数顺序。此外,您需要处理空列表[]
的情况,该列表实际上是在我给您的链接中提到的。