我是Haskell和函数式编程的新手。我正在尝试执行以下任务:
创建一个接受函数和列表的函数,如果函数对列表中的至少一个项返回true,则返回true,否则返回false。应该多态地工作。
我已经搜索了许多方法,包括Prelude和any
函数
any :: Foldable t => (a -> Bool) -> t a -> Bool
但是,我正在努力实施它们。这就是我所拥有的:
list = [2,3,45,17,78]
checkMatch :: Int -> Bool
checkMatch x
| x `elem` list = True
| otherwise = False
main = do
print (checkMatch 45)
有关如何使用Prelude或任何函数执行此任务的任何帮助。不要只是提供答案,请解释程序。问候。
好的。不是一个完整的答案,因为你想自己解决问题,但有些提示。
我强烈建议你先编写类型签名,直到你得到一个编译和处理一些案例的shell,然后填写函数定义。所以让我们从正确的类型签名开始吧。
在Haskell中,如果你想要一个带有任何类型参数的函数,你可以用不同的小写名称命名每个类型,通常是一个字母。特定类型具有大写名称,泛型类型为小写字母。因此,一个接受任何类型的参数并返回Bool的函数将具有类型签名a -> Bool
。对于第二个参数,您需要列出一些任意类型的元素。您希望将其元素传递给您的函数,因此它必须包含与函数域相同的类型,我们称之为a
。 (如果它可以保留任何内容,我们会选择另一个小写名称,例如b
。)您将该列表类型写为[a]
。你想要返回一个Bool
。
因此,您的类型签名应该是(a -> Bool) -> [a] -> Bool
。通常当我们编写一个对列表进行操作的函数时,一个好的方法是尾递归,我们将列表拆分为其头部和尾部(x:xs)
,使用x
执行某些操作,然后在xs
上再次调用该函数,直到最终得到一个空列表。您使用模板防护装置处于正确的轨道上,因此您可以从以下骨架开始:
checkMatch :: (a -> Bool) -> [a] -> Bool
checkMatch _ [] = _
checkMatch f (x:xs) | f x = _
| otherwise = _
main :: IO()
main = do
let shouldBeFalse = [1,3,5,7,9] :: [Int]
let shouldBeTrue = [1..10] :: [Int]
print (checkMatch (== " ") []) -- Does the empty string contain a space?
print (checkMatch even shouldBeFalse)
print (checkMatch even shouldBeTrue)
如果你编译它,GHC会告诉你它在程序中找到了三个“洞”,它们是第2,3和4行等号右侧的三个_
符号。(图中的_
)等号的左边意味着不同的东西:当列表为空时我们不关心函数参数是什么。为什么会这样?)它还会告诉你填充每个洞所需的类型是返回Bool
的表达式。它还将为您提供具有该类型的本地函数和变量的列表。如果你试图用f _
或checkMatch _ _
来填充其中一个洞,它会告诉你需要填写你创建的新洞的类型。
使用正确的程序逻辑填写所有孔,您的程序将起作用。
你正在寻找你的描述是一个函数,它接受一个谓词(这是一个带有一个或多个参数并返回一个布尔值的函数)和一个列表,如果列表中至少有一个元素满足谓词,则返回true 。
在Haskell中,上面的谓词是类型的函数:a -> Bool
。一个简单的例子可能是:
isEven :: Int -> Bool
isEven x = mod x 2 == 0`
取一个整数并返回它是否均匀。
所以,我们的功能是这样的:
isSatisfied :: (a -> Bool) -> [a] -> Bool
isSatisfied p [] = False
isSatisfied p (x:xs) = if (p x) then True else isSatisfied p xs
这定义了一个带有两个参数的函数。第一个是p
,它是第二个参数元素的谓词。它采用a
类型的元素,并返回true,无论它是否满足谓词。例如,如果列表中的某些元素是偶数,则isEven
将返回true:
Prelude> isSatisfied isEven [1]
False
但是,如果列表中有一些甚至:
Prelude> isSatisfied isEven [1,3,5,2,1,2]
True
我使用模式匹配来定义isSatisfied
:第一种情况是空列表,因为列表没有元素,没有元素满足谓词所以它应该评估为False
。非空案例以递归方式工作如下:首先检查谓词对齐列表x
的头部,导致两种可能性。如果x
满足谓词,我们找到了一个元素,我们应该返回True
。否则,我们继续检查列表的其余部分。
基本上,这是前奏中any
的定义:
Prelude> any isEven [1,2,3,4,5]
True
Prelude> any isEven []
False