如何使用镜头获取子列表的头部?

huangapple go评论50阅读模式
英文:

How to get sublist's head using lens?

问题

我有一个值:

my :: [(A, Either B [C])]


我想使用 [lens][1] 从中获取 `[(A, C)]`。结果项是来自 `my` 的项,满足以下条件:

1. 元组中的第二项是 `Right [C]`
2. 此 `Right [C]` 中的列表至少有 1 项,所以结果从中获取第一个(head)项

我知道如何获取 `[C]`,但我不知道如何获取 `[(A, C)]`。

[1]: https://hackage.haskell.org/package/lens
英文:

I have a value:

my :: [(A, Either B [C])]

and I want to get [(A, C)] from it using lens. The result items are items from my that:

  1. the second item in tuples is Right [C]
  2. the list in this Right [C] has at least 1 item, so the result get the first (head) item from it

I know how to get the [C] but I don't know how to get [(A, C)].

答案1

得分: 6

以下是您要翻译的内容:

你想要:

    my ^.. each . runFold (second (Fold (_Right . _head)))

这个想法是`_Right . _head`是一个从`Either B [C]`中选择`C`的折叠。您可以使用`Control.Arrow`中的`second`将其更改为从`(A, Either B [C])`中选择`(A, C)`。但是,为了实现这一点,您需要通过`Fold`将其实体化(即,将其转换为具有`Arrow`实例的新类型),然后使用`runFold`将其还原。生成的折叠专门用于:

    runFold (second (Fold (_Right . _head))) :: Fold (A, Either B [C]) (A,C)

它选择零个或一个`(A,C)`的实例,并且您可以将其与`each`组合起来折叠可遍历的容器,例如列表:

    runFold (second (Fold (_Right . _head))) :: Fold [(A, Either B [C])] (A,C)

以选择容器元素中的所有`(A,C)`

示例代码:

    import Control.Lens
    import Control.Arrow
    
    my :: [(Int, Either Double [Char])]
    my = [(1, Right "apple"), (2, Left 1.5), (3, Right "bear"), (4, Right "")]
    
    main = do
      print $ my ^.. each . runFold (second (Fold (_Right . _head)))

希望这有所帮助。如果您需要进一步的解释或有其他问题,请随时提问。

英文:

You want:

my ^.. each . runFold (second (Fold (_Right . _head)))

The idea is that _Right . _head is a fold that selects a C from an Either B [C]. You can make it select an (A, C) from an (A, Either B [C]), using second from Control.Arrow. However, to do this, you need to reify the fold (i.e., turn it into a newtype with an Arrow instance) using Fold and then unreify it with runFold. The resulting fold specializes to:

runFold (second (Fold (_Right . _head))) :: Fold (A, Either B [C]) (A,C)

which selects either zero or one instances of (A,C), and you can compose it with each to fold over a traversable container, like a list:

runFold (second (Fold (_Right . _head))) :: Fold [(A, Either B [C])] (A,C)

to select all of the (A,C) from the container's elements.

Sample code:

import Control.Lens
import Control.Arrow

my :: [(Int, Either Double [Char])]
my = [(1, Right "apple"), (2, Left 1.5), (3, Right "bear"), (4, Right "")]

main = do
  print $ my ^.. each . runFold (second (Fold (_Right . _head)))

huangapple
  • 本文由 发表于 2023年5月11日 18:46:12
  • 转载请务必保留本文链接:https://go.coder-hub.com/76226776.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定