英文:
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:
- the second item in tuples is 
Right [C] - 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)))
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。


评论