Lens.Internal.Indexed 如何连接到密钥容器?

How does Lens.Internal.Indexed connect to keyed containers?

为了将这个想法更进一步,可以将函数应用于可通过其索引遍历的任何元素。

import Control.Monad.State

updateAt :: forall a. Int -> (a -> a) -> [a] -> [a]
updateAt i f = flip evalState [0..] . traverse g
  where
    g :: a -> State [Int] a
    g x = do
        js <- get
        case js of
            [ ]      -> error ""
            (j: js') -> do
                put js'
                if j == i
                   then return (f x)
                   else return x

在 Haskell 中,尝试概括或以其他方式整理这样的操作。首先是 keys, then it grew up into lens。它现在是一个巨大的包裹。我正在尝试理解它。

为此,我试图先做简单的事情。一件简单的事情就是我开始做的——标记一个可遍历的。可以吗?此外,可以在 "low level" 上完成吗?

element seems to be doing the same as my example above, so I checked its definition. It led me to Indexable, then to this:

class ( Choice p, Corepresentable p, Comonad (Corep p)
      , Traversable (Corep p), Strong p, Representable p, Monad (Rep p)
      , MonadFix (Rep p), Distributive (Rep p), Costrong p, ArrowLoop p
      , ArrowApply p, ArrowChoice p, Closed p
      ) => Conjoined p

我承认这有点超出我的理解范围。我喜欢 "indexable" 听起来——它一定很有用。但它似乎也是 Haskell 有史以来最难的一篇文章。我知道 Conjoined 是一种高级的发音器,所以基本上……是一个函数?我不确定它可能是什么,以及这一切如何连接到键控容器。

它适用于我的问题吗?它是做什么用的?我怎样才能理解它?

Indexable i p 实际上只是表示“p(->)Indexed i (Indexed i a b = i -> a -> b)”。 lens 包建立在非常抽象的 类 塔上,使一切都变得非常笼统。具体来说,它不是使用函数,而是尝试使用一般的 profunctors,但是尝试处理索引基本上会导致整个事情崩溃(非常嘈杂,如您所见)到 "the profunctor is either (->) or Indexed i".

反正你不在乎Indexable。您所说的 "index" 是 element 的参数。 IndexedTraversable 中的 "index" 是一个 "result",由 IndexedTraversable 编辑的每个元素 return 也有与之关联的索引。在这里,它只是 returns 你再次传入的参数,以防其他人想要得到它。你不知道。要恢复 updateAt,只需将 element 的 return 值传递给 over,将 p 专门化为 (->) 并丢弃重复的索引:

updateAt :: Traversable t => Int -> (a -> a) -> t a -> t a
updateAt = over . element
-- updateAt i f = over (element i) f
-- "over element i do f"

我会说 over 很漂亮 "low-level"

-- basically
over :: ((a -> Identity b) -> (s -> Identity t)) -> (a -> b) -> (s -> t)
over setter f = runIdentity . setter (Identity . f)
-- I think even over = coerce would be valid
-- meaning it's actually just an identity function
-- and that updateAt = element (but with the type changed)

一般来说,我认为 "portal" 到 "operations on Traversable with indices" 是 traversed,基本上是 "is" traverse(当你专门化它的 p(->))。 elements = elementsOf traverse = elementsOf traversedelement = elementOf traverse = elementsOf traversed 只是过滤特定的索引。