Как Lens.Internal.Indexed соединяется с контейнерами с ключами? - PullRequest
0 голосов
/ 12 ноября 2019

Обходной путь может быть помечен. Чтобы продвинуть эту идею на один шаг дальше, можно применить функцию к любому элементу пересекаемого по его индексу.

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,есть попытка обобщить или иначе отсортировать операции, подобные этой. Сначала это было клавиш , затем оно переросло в объектив . Сейчас это огромный пакет. Я пытаюсь понять это.

С этой целью я сначала пытаюсь сделать простые вещи. Одна простая вещь - то, с чего я начал - маркировать проходимый. Это можно сделать? Кроме того, может ли это быть сделано на «низком уровне» ?

element, кажется, делает то же самое, что и мой пример выше, поэтому я проверил его определение,Это привело меня к Indexable, а затем к это :

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" звучит - это должно быть полезно. Но это также кажется самым трудным произведением на Хаскеле. Я понимаю, что Conjoined - продвинутый вид профессора, так что в основном ... функция? Я не уверен, что это может быть, и как все это связано с контейнерами с ключами.

Применимо ли это к моей проблеме? Для чего это? Как я могу понять это?

1 Ответ

2 голосов
/ 12 ноября 2019

Indexable i p действительно означает «p - это либо (->), либо Indexed i (Indexed i a b = i -> a -> b)». Пакет lens построен на башне очень абстрактных классов, что делает все очень общим. В частности, вместо того, чтобы работать с функциями, он пытается работать с общими профукторами, но попытка работать с индексами в основном заставляет все это рухнуть (очень шумно, как вы видели), чтобы просто «профюнктор был либо (->)»или Indexed i ".

В любом случае вас не волнует Indexable. «Индекс», о котором вы говорите, является аргументом element. «Индекс» в IndexedTraversable является «результатом», каждый элемент, возвращаемый IndexedTraversable, также имеет свой индекс, связанный с ним. Здесь он просто возвращает аргумент, который вы передали снова, на случай, если кто-то другой захочет его получить. Вы неЧтобы восстановить updateAt, просто передайте возвращаемое значение element в 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 довольно "низкоуровневый"

-- 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" to "на Traversable с индексами" равны traversed, что в основном "is" traverse (когда вы специализируете его p до (->)). elements = elementsOf traverse = elementsOf traversed и element = elementOf traverse = elementsOf traversed просто фильтруют по определенным индексам.

...