gpt4 book ai didi

haskell - 缩放和免费 monad 的困难

转载 作者:行者123 更新时间:2023-12-02 10:18:35 25 4
gpt4 key购买 nike

我正在研究免费的 monad 和lens,使用免费的 monad 创建我自己版本的 IO monad:

data MyIO next
= LogMsg String next
| GetInput (String -> next)
deriving (Functor)

我将其堆叠在状态单子(monad)的顶部,如下所示:FreeT MyIO (State GameState) a,其中GameState是:

data GameState = GameState { _players :: [PlayerState] }

现在,我想要的是一种从 GameState 上下文“放大”PlayerState 的方法。像这样的事情:

zoomPlayer :: Int -> FreeT MyIO (State PlayerState) a -> FreeT MyIO (State GameState) a
zoomPlayer i prog = hoistFreeT (zoom (players . element i)) prog

但我收到此错误:

No instance for (Data.Monoid.Monoid a1)
arising from a use of ‘_head’

此错误似乎与 players 相关。元素 i 是一次遍历;如果我从 _players 中删除列表方面并使用普通镜头,那么代码就可以工作。

关于如何编写这个函数有什么想法吗?

最佳答案

如果您确定永远不会索引到不存在的玩家并且不介意一点不安全,您可以使用unsafeSingular组合器将 Traversal 转换为 Lens,如下所示:

zoomPlayer :: Int -> FreeT MyIO (State PlayerState) a -> FreeT MyIO (State GameState) a
zoomPlayer i prog = hoistFreeT (zoom (players . unsafeSingular (element i))) prog

(另外,也许我会使用 ix 而不是 element,但这与问题无关。)

我们还可以为始终无限的序列构建安全的索引透镜,例如使用 Cofree 定义的流来自免费包:

import Control.Lens (Lens', _Wrapped')
import Control.Comonad.Cofree (Cofree, telescoped)
import Data.Functor.Identity
import Control

sureIx :: Int -> Lens' (Cofree Identity a) a
sureIx i = telescoped $ replicate i _Wrapped'

但是游戏不可能有无限的玩家。

关于haskell - 缩放和免费 monad 的困难,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29478398/

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