gpt4 book ai didi

Haskell、Lenses、Getter 和 Setter

转载 作者:行者123 更新时间:2023-12-04 02:43:38 24 4
gpt4 key购买 nike

我无法理解 Haskell 中镜头库的所有细微差别。

假设我有以下镜头

activePlayer :: Lens' Game Player
activePlayer = lens get set
where
get (Game {_players = (index, seq) }) = S.index seq index
set g@(Game {_players = (index, seq) }) player =
g { _players = (index, S.update index player seq) }

在 ghci 提示符下执行以下操作没有问题:
> :t do{use (activePlayer); activePlayer.= undefined}
:: Control.Monad.State.Class.MonadState Game m => m ()

但是,当我尝试将其参数化为函数时,出现以下错误。
> :t \p -> do{use p; p.=undefined}
<interactive>:1:17:
Couldn't match type `Accessor a0 a0' with `Mutator b0'
Expected type: ASetter s0 s0 a0 b0
Actual type: Getting a0 s0 a0
In the first argument of `(.=)', namely `p'
In a stmt of a 'do' block: p .= undefined
In the expression:
do { use p;
p .= undefined }

看起来像 p被推断为 Accessor , 当我希望它被推断为完整的 Lens .我尝试强制 p成为 Lens有以下内容,但 ghci 在 Lens' a b 中提示 RankNTypes .
:t \p -> do{use p; p.=undefined} :: Lens' a b -> m c

如果有人能帮我找出原因,我将不胜感激 p正在推断它的方式,以及我如何使它表现得像一个完整的 Lens .

最佳答案

怎么了?

发生这种情况的原因是,如果您查看 Lens' 的类型:

type Lens' s a = forall f. Functor f => (a -> f a) -> s -> f s

这实质上是让您能够以 Lens' 进行交易。在 Functor f 中任意一种选择你要。但是, use想挑 Accessor a , 而 .=想挑 Mutator .

怎么做你问的

如果你通过了 Lens并且想要多次使用它并选择不同的仿函数,您需要

a.) 以更高等级的类型通过它
 {-# LANGUAGE RankNTypes #-}

foo :: MonadState a m => Lens' a b -> m ()
foo p = do
use p
p .= undefined

b.) cloneLens在您将其用于阅读和/或写作之前。
:t \p -> do{use (cloneLens p); cloneLens p.=undefined}

使用 cloneLens在每一侧都会对 Functor 做出一致的选择,每次都会生成一个新的镜头。

c.) 使用 Control.Lens.Loupe 中的组合子.
:t \p -> do gets (^# p); p #= undefined

这些旨在始终做出与 cloneLens 相同的选择。将。

如何做你可能想做的事

在实践中,最好使用另一种方法,例如
:t \p -> p %= \oldValue -> newValue

因为这将支持任何 TraversalSetter ,而不仅仅是 Lens ,为您打开更多用例。

如果您需要获取该值以供将来计算:
:t \p -> p %%= \oldValue -> (whatYouWantToReadFromIt, whatYouWantToWriteToIt)

关于Haskell、Lenses、Getter 和 Setter,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20626963/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com