data Fruit = Apple Int
           | Banana Color Int
           
data Color = Red
           | Green
           
let basket = [Apple 3,Banana Red 30,Apple 6]

目标是Banana只保留

如何删除列表中的所有 Apple {} basket?使用遍历()?

一旦traversal 建成,我就可以删除它们,修改它们(覆盖),更改它们(设置)

谢谢 !

8

  • 您可能想看看filter功能。


    – 

  • @nmcouldbeanAIfilter只能过滤,但遍历才能modify选择replace


    – 

  • 1
    你的意思是什么traversal?标准traverse功能根本无法过滤。


    – 

  • @Carl 。遍历应能够聚焦结构内的 0 个或 N 个元素


    – 

  • 2
    “此要求的一个结果是,遍历需要留下与开始时相同数量的元素作为后续遍历的候选。”


    – 


最佳答案
1

无法使用Traversals 完成此操作。无论是traverse遍历都不允许这样做。

原因是遍历具有重要的属性,即它们不会改变容器的整体“形状”。它们不能添加或删除元素。正如所述Traversable

函子表示可以转换为相同形状结构的数据结构

文档确实lens说遍历可以让你“关注”结构的某些元素。但这意味着你可以设置修改这些元素。你无法删除它们。


如果您正在寻找Traversable允许(可能有效的)过滤操作的容器类,那么可以Filterable包中找到Witherable


但对于你来说,我只需做类似的事情

removeApples :: [Fruit] -> [Fruit]
removeApples = mapMaybe (\f -> case f of
   Apple {} -> Nothing
   other -> Just other)

removeApples2 :: [Fruit] -> [Fruit]
removeApples2 = foldMap (\f -> case f of
   Apple {} -> []
   other -> [other])

removeApples3 :: [Fruit] -> [Fruit]
removeApples3 fruits = do -- list monad
   fruit <- fruits
   case fruit of 
    Apple {} -> []
    other -> [other]

removeApples4 :: [Fruit] -> [Fruit]
removeApples4 = filter (\f -> case f of
   Apple {} -> False
   other -> True)

2

  • 有没有一种方法可以将Apple函数签名参数化,这样下次用户想要时它看起来是通用的remove Banana?这样可以避免再次重写几乎相同的函数(只需替换AppleBanana


    – 

  • @ShawnZhang “镜头”包(也称为“光学”包)具有 的概念Prism。您可以为 sum 类型创建它们,并将它们用作某种“一流模式”来定义谓词函数,借助has或 等组合器hasn't。示例:


    –