【问题标题】:How to implement the function find with the filter function?如何用过滤功能实现查找功能?
【发布时间】:2019-09-05 06:01:13
【问题描述】:

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

我已经实现了没有filter 函数的find 函数(参见下面的代码块),但现在我的问题是用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 的结果。

【问题讨论】:

  • find1 需要空列表的基本情况吗?如果您只想要第一个结果,请使用 head 但知道它不安全(如果在列表中找不到匹配的元素,则会出错)
  • 看来 OP 正在寻找 filter 的重新实现(而不是 find)。他似乎用find的名字称呼filter

标签: haskell filter find


【解决方案1】:

要“剪切一个列表”以使其中只有一个 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:对于某些x :: tMaybe t 类型的值可以是NothingJust x(阅读:x 具有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。为此,只需遵循类型,并编写枚举可能输入情况的方程式,在每种情况下生成适当的输出类型值,就像我们在上面对take1 所做的那样。

【讨论】:

  • 感谢您改进我的功能,但不幸的是,这不是我要找的 awnsere。我仍在寻找使用过滤器实现的功能 find 。最好的问候:)
  • 我给了它两次,take 1 $ find2 ...,或者find22,不是吗? :) 你的意思是你需要take 1listToMaybe 实现提示吗?
  • 我添加了一些东西,但我必须说,回答多管齐下的问题并不好玩。它使答案变得混乱。以后请始终就某一特定代码 sn-p 提出一个问题。
猜你喜欢
  • 1970-01-01
  • 2018-12-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-03-26
  • 2019-07-05
  • 2020-07-10
  • 2018-09-30
相关资源
最近更新 更多