You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

求兼容Control.Lens的Comonad聚焦及Store Comonad位置交互透镜

Working with Lenses for Store Comonad Focus and Position

Absolutely, you can create lenses compatible with Control.Lens to interact with both the focused value (retrieved via extract) and the position (pos) of a Store comonad—including modifying just the focused value without touching other parts of the store. Let’s walk through how to do this.

First, a Quick Recap of Store Comonad Structure

A Store s a wraps two core components:

  • A "peek" function s -> a that maps positions to values
  • A current position s (directly accessible via the pos function)

The focused value returned by extract is simply peek store (pos store)—the value tied to the store’s current position.

1. Lens for the Focused Value (extract Result)

This lens lets you get or update the value at the store’s current position, while leaving the peek function’s behavior for other positions and the current position itself unchanged:

import Control.Lens
import Control.Comonad.Store

focused :: Lens' (Store s a) a
focused = lens extract updateFocus
  where
    updateFocus store newVal = 
      store { peek = \pos' -> if pos' == pos store then newVal else peek store pos' }

How it works:

  • The getter leverages extract to pull the current focused value directly.
  • The setter creates a new store where the peek function returns newVal only when the position matches the original store’s current position; all other positions retain the original peek behavior.

2. Lens for the Store’s Position (pos)

This one is straightforward—since pos is a direct field of the Store type, we can build a lens to get or set it with minimal code:

position :: Lens' (Store s a) s
position = lens pos (\store newPos -> store { pos = newPos })

Example Usage

Let’s put these lenses into action with a concrete example:

-- Create a store: peek adds 10 to any position, current position is 5 (so extract gives 15)
myStore :: Store Int Int
myStore = store (+10) 5

-- View the focused value
view focused myStore  -- Returns 15

-- View the current position
view position myStore  -- Returns 5

-- Modify only the focused value (set it to 20)
updatedFocusStore = myStore & focused .~ 20
extract updatedFocusStore  -- Returns 20
peek updatedFocusStore 3   -- Still returns 13 (original behavior for other positions)

-- Change the position to 7
updatedPosStore = myStore & position .~ 7
extract updatedPosStore  -- Returns 17 (10 + 7)

Compatibility with Control.Lens

Since these are proper Lens' values, you can combine them with any of Control.Lens’s combinators. For example:

  • Use over focused (*2) to double the focused value
  • Chain lenses with other optics (like nested stores or record fields)
  • Use preview focused if you want a Maybe a (though for Store, this will always return Just since extract is total)

Notes on General Comonads

If you’re curious about a lens that works with any comonad’s extract value, keep in mind that not all comonads support modifying this value—many (like Identity or Env) have immutable focused values. But for Store, which is designed to be navigable and mutable in this way, the focused lens works perfectly.

内容的提问来源于stack exchange,提问作者Chris Penner

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.21 07:26:02