接受函数和列表并返回布尔值的函数

时间:2017-12-31 20:31:56

标签: function haskell functional-programming

我是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或任何函数执行此任务的任何帮助。不要只是提供答案,请解释程序。问候。

2 个答案:

答案 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