我是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或任何函数执行此任务的任何帮助。不要只是提供答案,请解释程序。问候。
答案 0 :(得分:6)
好。不是一个完整的答案,因为你想自己解决问题,但有一些提示。
我强烈建议您首先编写类型签名,直到获得编译和处理一些案例的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 _ _
部分填充其中一个洞,它会告诉你填写你创建的新洞需要什么类型。
使用正确的程序逻辑填写所有孔,您的程序将正常工作。
答案 1 :(得分:1)
你正在寻找你的描述是一个函数,它接受一个谓词(这是一个带有一个或多个参数并返回一个布尔值的函数)和一个列表,如果列表中至少有一个元素则返回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