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

问题描述 投票:2回答:2

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

function haskell functional-programming
2个回答
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
投票

你正在寻找你的描述是一个函数,它接受一个谓词(这是一个带有一个或多个参数并返回一个布尔值的函数)和一个列表,如果列表中至少有一个元素满足谓词,则返回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
© www.soinside.com 2019 - 2024. All rights reserved.