gpt4 book ai didi

Haskell - 镜头,使用 'to' 函数

转载 作者:行者123 更新时间:2023-12-04 03:38:11 25 4
gpt4 key购买 nike

我有以下代码。我希望能够在给定游戏状态时修改活跃玩家的生活。我想出了一个 activePlayer镜头,但是当我尝试将它与 -= 结合使用时运算符(operator)我收到以下错误:

> over (activePlayer.life) (+1) initialState 
<interactive>:2:7:
No instance for (Contravariant Mutator)
arising from a use of `activePlayer'
Possible fix:
add an instance declaration for (Contravariant Mutator)
In the first argument of `(.)', namely `activePlayer'
In the first argument of `over', namely `(activePlayer . life)'
In the expression: over (activePlayer . life) (+ 1) initialState``

和有问题的代码:
{-# LANGUAGE TemplateHaskell #-}
module Scratch where

import Control.Lens
import Control.Monad.Trans.Class
import Control.Monad.Trans.State
import Data.Sequence (Seq)
import qualified Data.Sequence as S

data Game = Game
{ _players :: (Int, Seq Player) -- active player, list of players
, _winners :: Seq Player
}
deriving (Show)

initialState = Game
{ _players = (0, S.fromList [player1, player2])
, _winners = S.empty
}

data Player = Player
{ _life :: Integer
}
deriving (Show, Eq)

player1 = Player
{ _life = 10
}

player2 = Player
{ _life = 10
}

makeLenses ''Game
makeLenses ''Player

activePlayer
:: (Functor f, Contravariant f) =>
(Player -> f Player) -> Game -> f Game
activePlayer = players.to (\(i, ps) -> S.index ps i)

每个玩家按顺序轮到他们。我需要同时跟踪所有玩家以及当前活跃的玩家,这就是我如何构建它的原因,尽管我对不同的结构持开放态度,因为我可能还没有合适的结构。

最佳答案

当您使用 (.) 在镜头库中构图各种项目时他们可能会根据一种子类型而失去能力(见下文)。在这种情况下,您已经编写了 Lens ( players ) 与 Getter ( to f 对于某些功能 f )因此组合只是 Getterover作用于可以获取和设置的镜头。
activePlayer但是,应该形成一个有效的镜头,因此您可以手动将其编写为 getter/setter 对。我在假设索引永远不会无效的情况下将其部分写在下面。

activePlayer :: Lens' Game Player
activePlayer = lens get set
where
get :: Game -> Player
get (Game { _players = (index, seq) }) = Seq.index seq index

set :: Game -> Player -> Game
set g@(Game { _players = (index, seq) }) player =
g { _players = (index, Seq.update index player seq) }

为了更好地理解 lens 中出现的子类型我们可以使用的库 the Big Lattice Diagram from Hackage

the Big Lattice Diagram from Hackage

每当您将两种镜头类型与 (.) 结合使用时您最终会在该图表中找到他们的第一个共同后代。所以如果你结合 LensPrism你可以看到他们的箭头会聚在 Traversal .如果结合 LensGetter (其中 to f 是)然后你得到一个 Getter自从 GetterLens 的直系后代.

关于Haskell - 镜头,使用 'to' 函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20528718/

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