【问题标题】:Map then filter in Haskell映射然后在 Haskell 中过滤
【发布时间】:2021-10-04 17:15:39
【问题描述】:

我想在 Haskell 中映射一个 Integer 类型列表,然后如果 map 函数返回 Nothing 我想丢弃结果。我正在尝试编写的函数的类型签名为

mapThenFilter :: (Integer -> Maybe Integer) -> [Integer] -> [Integer]

到目前为止,我已经考虑过这样做:

checkIfNothing value = case value of 
     Just a -> a
     Nothing -> 0

mapThenFilter = map checkIfNothing(map f l)

但这是不正确的。我是Haskell的新手,所以如果可能的话,你能告诉我我哪里出错了吗?我相信既然这是 Map then Filter,那么 Haskell 过滤器函数可能也会被使用,但是,我相信我的函数定义中的外部 map 函数正在完成预期的工作(过滤器函数)对吗?

【问题讨论】:

  • map 永远不能替代filter,因为filter 返回一个删除了一些项目的新列表,而map 总是返回一个相同长度的列表
  • 您给出的定义本身并没有多大意义,但假设您的意思是 mapThenFilter f l = map checkIfNothing(map f l) 以便它编译,那么这并不遥远。它只是用 0 替换 fNothing 的所有元素,而不是删除它们。您应该能够使用它来解决问题,即使它不是您首先提出的最短或最惯用的解决方案。

标签: haskell functional-programming filtering higher-order-functions map-function


【解决方案1】:

如 cmets 中所述,您正在重新实现 mapMaybe

哪个好。这是一个不明显的功能,很高兴您觉得需要它并提出这个想法,并以它的类型表达。

如果您想按照自己的方式进行操作,那么实际上您已经有了一个良好的开端。不过需要调整一下:

checkIfNothing value = case value of 
     Just a -> a
     Nothing -> 0    

0 太具体了,还是用[]吧。但是现在简单地返回a 将不起作用。让我们也把它放在一个列表中:

checkIfNothing :: Maybe t -> [t]
checkIfNothing value = case value of 
     Just a -> [a]
     Nothing -> []    

所以现在,

mapThenFilter f l  =   map checkIfNothing (map f l)

几乎是对的。我们在列表中生成结果,而那些被跳过的结果为空列表:

   -- instead of
   [ a,   b,  c, .... , z ]
   -- we produce
   [ [], [b], [], .... , [z] ]

所以我们只需要将它们连接起来,将它们与++s 连接在一起:

     []++[b]++[]++...,++[z]  

   [      b,       ...., z   ]

所以我们定义

mapThenFilter :: (a1 -> Maybe a) -> [a1] -> [a]
mapThenFilter f l  =  concat $ map checkIfNothing (map f l)

顺便说一句,checkIfNothing 也已经存在。它被称为maybeToList

> foo f l = concat $ map maybeToList $ map f l
foo :: (a1 -> Maybe a) -> [a1] -> [a]

> foo (\x -> listToMaybe [x | even x]) [1..10]
[2,4,6,8,10]

concatmap 的组合非常重要,可以分配一个特殊功能来完成其工作,concatMap。而且该功能非常重要,甚至可以分配一个特殊的运算符来完成它的工作:

foo f = concat . map maybeToList . map f  
      = concat . map (maybeToList . f)
      = concatMap (maybeToList . f)
      = (maybeToList . f  =<<)

【讨论】:

    猜你喜欢
    • 2021-05-16
    • 2018-02-23
    • 2019-09-04
    • 2019-12-10
    • 1970-01-01
    • 2023-03-25
    • 2019-04-17
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多