Линзы над Comonads или Представимым

Вот более конкретный вариант этого вопроса: мутировать только фокус Store Comonad?, чтобы не задавать более одного вопроса одновременно.

Существуют ли какие-либо объективы, совместимые с Control.Lens, которые позволяют мне взаимодействовать с фокусом комонады (значение от extract) или с индексом / значением магазина Comonad (pos)?

Кажется, что линзы могут быть здесь полезны, но я не смог найти ничего подходящего; любая помощь будет оценена, спасибо!

1 ответ

Решение

Comonad не дает вам никакого способа переписать фокус комонады, поэтому вы не можете написать общий Lens за extract, Но очень легко превратить любую старую функцию в Getter:

extracted :: Comonad w => Getter (w a) a
extracted = to extract

Конечно, многие комонады позволяют писать в фокусе - Store, как вы упомянули, но также (включая, но не ограничиваясь) Env, Traced а также Identity,

-- I suspect some of these laws are redundant:
--   write id = id
--   write f . write g = write (f . g)
--   extract . write f = f . extract
--   duplicate . write f = write (write f) . duplicate
--   write (const (extract w)) w = w
class Comonad w => ComonadWritable w where
    write :: (a -> a) -> w a -> w a

instance ComonadWritable Identity where
    write f (Identity x) = Identity (f x)

-- law-abiding "up to Eq"
instance (Eq s, ComonadWritable w) => ComonadWritable (StoreT s w) where
    write f (StoreT w s) = StoreT (write g w) s
        where
            g k s'
                | s' == s = f (k s')
                | otherwise = k s'

-- law-abiding "up to Eq"
instance (Eq m, Monoid m, ComonadWritable w) => ComonadWritable (TracedT m w) where
    write f (TracedT w) = TracedT (write g w)
        where
            g k m
                | m == mempty = f (k m)
                | otherwise = k m

instance ComonadWritable w => ComonadWritable (EnvT e w) where
    write f (EnvT e w) = EnvT e (write f w)

Дано ComonadWritable это легко построить Lens для внимания комонады.

focus :: ComonadWritable w => Lens' (w a) a
focus = lens extract (\w x -> write (const x) w)

Одно замечание по эффективности: StoreT а также TracedT "s write реализации строят цепочку функций с проверками на равенство по пути вниз, поэтому extract O(n) в количестве write звонки. Поскольку вы упомянули, что вы используете Representable комонада w, вы могли бы реализовать некоторую умную стратегию пакетного редактирования и преобразования их в реальный w очень часто Или вы можете хранить изменения в Map (укрепляя Eq ограничение к Ord) и делегировать в основной w когда оказывается, что элемент не был отредактирован. Я оставлю эту часть тебе.

Другие вопросы по тегам