Lenses over Comonads or Representable

℡╲_俬逩灬. 提交于 2019-12-08 20:15:28

Comonad doesn't give you any way to write back to the comonad's focus, so you can't write a general Lens for extract. But it is very easy to turn any old function into a Getter:

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

Of course many comonads do allow you to write into the focus - Store, as you mentioned, but also (including but not limited to) Env, Traced and 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)

Given ComonadWritable it's easy to construct a Lens for a comonad's focus.

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

One note on efficiency: StoreT and TracedT's write implementations build a chain of functions with equality checks on the way down, so extract is O(n) in the number of write calls. Since you mentioned you're using a Representable comonad w, you could implement some clever strategy of batching up edits and reifying them into an actual w every so often. Or you could store edits in a Map (strengthening the Eq constraint to Ord) and delegate to the underlying w when it turns out an element hasn't been edited. I'll leave that part to you.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!