有条件地修改镜头的目标

Modifying the target of a Lens conditionally

我有一个函数可以根据输入和棋盘生成更新的棋盘,前提是游戏规则允许移动:

move :: Input -> Board -> Maybe Board

电路板包装在 GameState 类型中,带有一些附加数据:

type GameState = (Board, ...)

现在,如果 move 产生 Just 一个值,我想在游戏状态下使用镜头更新棋盘。 我可以使用辅助函数来做到这一点:

updateGameState :: Input -> GameState -> GameState
updateGameState input gs = gs & _1 %~ (f $ move input)
  where
    f g x = maybe x id (g x)

但是,我想知道是否有一个组合器可以修改 a 的目标 Lens 仅当提供的函数 returns a Just 时。我找到了 ?~ 运算符,但它处理左侧的偏向性。

是否有(可能更通用的)组合器可以实现这一点,或者是否有另一种方式以简洁和惯用的方式表达这一点?

你可以做到

import Control.Applicative
import Data.Maybe

updateGameState :: Input -> GameState -> GameState
updateGameState input = fromMaybe <*> _1 (move input)
-- updateGameState x s = fromMaybe s $ _1 $ move x

这利用了 Lens s t a bforall f . Functor f => (a -> f b) -> (s -> f t) 的类型别名这一事实,因此我们可以选择将 Maybe 用作 f 并获得类型 GameState -> Maybe GameState.