本文介绍了镜头在Comonads或可代表的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

以下是这个问题的一个更具体的变体:,因为不会一次询问多个问题。

是否有与,它允许我与一个comonad的焦点进行交互(从 extract )或与Store Comonad的索引/值( pos )?



好像镜片可能是有些在这里使用,但我一直无法找到任何合适的东西;任何帮助将不胜感激,谢谢!

解决方案

Comonad 不给你任何回复comonad焦点的方法,所以你不能为 extract 写一个通用的 Lens 。但:

 提取:: Comonad w => Getter(wa)a 
extract = to extract

当然,许多comonads 允许您写入焦点 - Store ,正如您所提到的,但也包括(包括但不限于) Env ,跟踪和身份。

   - 我怀疑这些定律有些是多余的:
- write id = id
- write f。写g =写(f。g)
- 提取。写f = f。提取
- 重复。写入f =写入(写入f)。复制
- write(const(extract w))w = w
class Comonad w => ComonadWritable w其中
写入::(a - > a) - > w a - > wa

实例ComonadWritable身份其中
写入f(身份x)=身份(fx)

- 守法达到公式
实例(等式,ComonadWritable w)=> ComonadWritable(StoreT s w)其中
写入f(StoreT w s)= StoreT(写入g w)s
其中
g k s'
| s'== s = f(k s')
|否则= k s'

- 守法直到Eq
实例(Eq m,Monoid m,ComonadWritable w)=> ComonadWritable(TracedT m w)其中
写入f(TracedT w)= TracedT(写入g w)
其中
g k m
| m == mempty = f(k m)
|否则= k m

实例ComonadWritable w => ComonadWritable(EnvT ew)其中
写入f(EnvT ew)= EnvT e(写入fw)



<给定 ComonadWritable 可以很容易地为一个comonad的焦点构造一个 Lens 。

  focus:ComonadWritable w =>镜头'(wa)a 
焦点=镜头提取物(\ wx - > write(const x)w)

关于效率的一点说明: StoreT 和 TracedT 的写入实现构建了一个函数链,并在下降时进行了相等性检查,因此提取中的O(n)为写调用。既然你提到你正在使用一个可表示的 comonad w ,你可以实施一些聪明的策略来批量修改和重写他们每隔一段时间就会变成一个实际的 w 。或者,您可以将编辑存储在 Map 中(将 Eq 约束强化为 Ord )并委托给底层的 w ,当它发现一个元素尚未被编辑。我会把那部分留给你。


Here's a more specific variant of this question: Mutate only focus of Store Comonad?, for the benefit of not asking more than one question at once.

Are there any lenses compatible with Control.Lens which allow me to interact with the focus of a comonad (the value from extract) or with the index/value of the Store Comonad (pos)?

It seems like lenses may be of some use here, but I have been unable to find anything which fits; any help would be appreciated, thanks!

解决方案

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.

这篇关于镜头在Comonads或可代表的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

10-19 09:07