变焦有“双重”作用吗?

时间:2018-08-16 11:33:17

标签: haskell lens state-monad lenses

zoom允许我们在实际上定义了更多变量的情况下使用仅使用一些状态变量的状态动作。

{-# LANGUAGE TemplateHaskell #-}

import Control.Lens

import Control.Monad.Trans.State
import Control.Monad.IO.Class

data Galaxy = Galaxy {
    _solarSys :: SolarSystem
  , _otherStars :: String
  } deriving (Show)
data SolarSystem = SolarSystem {
    _sun :: Float
  , _planets :: Int
  } deriving (Show)

makeLenses ''SolarSystem
makeLenses ''Galaxy

main = (`runStateT`Galaxy (SolarSystem 2e+30 8) "") $ do
   zoom solarSys $ do
      sun -= 1e+23
      planets += 1
   liftIO . print =<< get
Galaxy {_solarSys = SolarSystem {_sun = 1.9999999e30, _planets = 9}, _otherStars = ""}

但是,如果我想在仅定义了一些状态变量的环境中做一些事情,然后运行包含一些额外的局部状态变量的计算,该怎么办?喜欢

data Expedition = Expedition {
    _environment :: SolarSystem
  , _spacecraft :: Char
  } deriving (Show)
makeLenses ''Exploration

main = (`runStateT`Galaxy (SolarSystem 2e+30 8) "Milky") $ do
   zoom solarSys $ do
      spectralFilter environment (spacecraft ???~= '') $ do
         spacecraft .= '️'
         environment . planets -= 1
   liftIO . print =<< get

我怀疑spacecraft的初始化实际上还需要其他光学元件,但我看不到。

1 个答案:

答案 0 :(得分:4)

该功能如何?

cram :: Monad m => Iso' s' (s,x) -> x -> StateT s' m r -> StateT s m r
cram someiso extra action =
    StateT (\small0 -> do let big0 = view (from someiso) (small0,extra)
                          (r,big) <- runStateT action big0
                          let (small,_) = view someiso big
                          pure (r,small))

“如果您说服我扩展状态是小状态加额外的东西,并且给我一些初始的额外东西,我可以将扩展状态计算塞入小状态。”

您将必须编写Iso' Expedition (SolarSystem,Char)