镜头超过共群或可代表

Chr*_*ner 5 haskell comonad haskell-lens representable

这是这个问题的一个更具体的变体:Mutate only focus of Store Comonad?,以免一次问多个问题。

是否有任何与Control.Lens兼容的镜头允许我与 comonad 的焦点(来自 的值extract)或 Store Comonad ( pos)的索引/值进行交互?

似乎镜头在这里可能有用,但我一直找不到适合的东西;任何帮助将不胜感激,谢谢!

Ben*_*son 3

Comonad没有给你任何写回comonad焦点的方法,所以你不能写一个通用Lensextract. 但是将任何旧函数变成一个非常容易Getter

extracted :: Comonad w => Getter (w a) a
extracted = to extract
Run Code Online (Sandbox Code Playgroud)

当然,正如您提到的,许多comonad确实允许您写入焦点 - Store,但也(包括但不限于)Env,TracedIdentity

-- 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)
Run Code Online (Sandbox Code Playgroud)

鉴于ComonadWritable构建Lenscomonad 的焦点很容易。

focus :: ComonadWritable w => Lens' (w a) a
focus = lens extract (\w x -> write (const x) w)
Run Code Online (Sandbox Code Playgroud)

关于效率的一个注释:StoreTandTracedTwrite实现构建了一个函数链,在向下的过程中进行相等性检查,调用extract次数也是 O(n) write。既然您提到您正在使用Representablecomonad w,您可以实施一些聪明的策略来批量编辑并w经常将它们具体化为实际内容。或者,您可以将编辑存储在 a 中Map(加强对Eq的约束),并在发现元素尚未编辑时Ord委托给底层。w我会把这部分留给你。