【问题标题】:How to snoc using the lens library?如何使用镜头库进行 snoc?
【发布时间】:2014-01-23 22:07:19
【问题描述】:

在尝试使用 Edwards lens 库时,我很难过 again。我尝试在状态上下文中将 snoc 一些东西放到向量的末尾:

data Foo = Foo {
  _vec :: Vector Int
}

makeLenses ''Foo

testCons x = vec <>= singleton x

虽然这可行,但我想使用[cons][2],但我不知道如何使用。文档中提到了[0,1,2] |&gt; 3 === [0,1,2,3],但我不知道如何在状态上下文中执行此操作。

【问题讨论】:

  • 你会添加很多元素吗?如果是这样,您应该改用Sequence。对 Vector 进行 consing/snocing 是 O(n),但对于 Sequence 是 O(1);另一方面,与向量的 O(1) 相比,序列具有 O(log n) 的随机访问。
  • @Kata yay ...我知道 :-) ...我可能应该在实际代码中使用 Foo f a = Foo (f a)

标签: haskell haskell-lens


【解决方案1】:

(%=) 组合器让您可以将函数应用于镜头的目标;你想要类似的东西

stateSnoc :: MonadState Foo m => Int -> m ()
stateSnoc x = vec %= (|> x)

【讨论】:

  • 虽然这可行,但我错过了其他 lens 函数的一些优雅。
  • “优雅”是什么意思?
  • 我期待像vec += x 这样的东西。虽然这当然是为Num 保留的。
  • 我想这和你想得到的一样漂亮。没有设置器指向“后面”最后一个元素,因为,那有什么意义呢?那里永远不会有任何有趣的值。
  • 接受,因为它显然是正确的。但我建议也阅读其他答案。
【解决方案2】:

snoc 似乎是为方便起见从原始Prism 定义的普通函数,即_Snoc

那么为什么不使用普通的MonadState 函数,比如modify

runState (modify $ flip snoc 'a') ['b']
-- ((),"ba")

【讨论】:

  • 我必须将它与zoom 结合起来才能专注于嵌套条目......但是有没有办法直接使用_Snoc?喜欢foo . vec . _Snoc .= bar
  • _Snoc 棱镜的默认方向是从一个集合到一对(collection minus the last element, last element)。但是您可以使用review 函数“扭转局面”,并编写类似review _Snoc $ (['b'],'a') 的内容。这几乎是snoc 的定义,但没有咖喱。但请注意,review _Snoc 不是镜头,而是常规功能。
  • 更正:review 的结果适用于任何MonadReader
  • 嗯......它并没有好转:)......我的猜测是有某种镜头/设置器指向容器“后面”。
  • @Florian 我怀疑有一个Setter 可用于附加到容器。 Setters 必须遵守的(非常直观的)法则之一是,用两个不同的值设置两次等于只用最后一个值设置一次。但是将'a'然后'b'附加到某些东西不等于只附加'b'!我怀疑附加和解构本质上是Prism-like。
猜你喜欢
  • 2013-12-05
  • 2015-01-03
  • 2022-01-05
  • 1970-01-01
  • 1970-01-01
  • 2023-03-15
  • 2019-04-09
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多