如何用过滤功能实现功能查找?

时间:2019-04-15 09:19:50

标签: haskell filter find

我正在做些运动以练习Haskell技能。我的任务是自己使用find函数来实现Haskell函数filter

我已经实现了没有find函数的filter函数(请参见下面的代码块),但是现在我的问题是要使用filter函数来实现它。

-- This is the `find` function without `filter` and it's working for me.

find1 e (x:xs)= if e x then x
        else find1 e xs

-- This is the find function with the filter function 

find2 e xs = filter e xs

find1的结果正确

*Main> find1(>4)[1..10]
Output : [5].

但是我写过滤器的实际任务是给我

*Main> find2(>4)[1..10]
Output : [5,6,7,8,9,10].

我想要的find2结果是find1的结果。

1 个答案:

答案 0 :(得分:2)

要将“剪切列表”仅包含一个head元素,请使用take 1

> take 1 [1..]
[1]

> take 1 []
[]

> take 1 $ find2 (> 4) [1..10]
[5]

> take 1 $ find2 (> 14) [1..10]
[]

如果您需要实现自己的take 1函数,只需根据每种可能的输入情况写下其方程式:

take1 [] = []
take1 (x:xs) = [x]

或者使用filter

findWithFilter p xs = take1 $ filter p xs

您的find1定义与您显示的输出不对应。相反,以下定义将:

find1 e (x:xs) = if e x then [x]     -- you had `x`
                   else find1 e xs
find1 _ []     = []                  -- the missing clause

习惯上将谓词p而不是e称为助记符设备。强烈建议将类型签名添加到所有顶级定义中。

如果您自己编写困难,可以先不使用签名,然后询问GHCi推断出哪种类型,而不是使用该签名如果它确实表达了您的意图 –否则就意味着您已经编码了不同的内容:

> :t find1
find1 :: (t -> Bool) -> [t] -> [t]

第一次尝试似乎不错。

除了,您实际上希望输出列表中的元素永远不超过1个:对于某些[],它是[x]x,永远不超过一个。

列表[]的类型在这里太宽容了,因此不完美。

虽然确实存在这种类型。它称为Maybe:对于某些Maybe t,类型Nothing的值可以是Just xx :: t(读:x的类型是{{ 1}}):

t

我们甚至不必在这里import Data.Maybe (listToMaybe) find22 p xs = listToMaybe $ filter p xs :函数take 1(读:具有一种类型的函数,在listToMaybe :: [a] -> Maybe a中输入,在[a]中输出)从输入列表中最多获取一个元素,因为结果类型不允许有多个元素-它根本没有更多空间。因此,它正确表达了我们的意图:最多生成一个元素(如果有):

Maybe a

在确定确实需要时,在其定义上方添加完整签名:

> find22 (> 4) [1..10]
Just 5

> find22 (> 14) [1..10]
Nothing

接下来,自己实施find22 :: (a -> Bool) -> [a] -> Maybe a 。为此,只需遵循类型,然后编写方程式枚举可能的输入情况,就可以在每种情况下产生适当的输出类型值,就像我们上面对listToMaybe所做的那样。