使用以下代码片段:
data Circle = Circle
{ center :: Point
, radius :: Double
}
data Point = Point (Double, Double)
someFuncOverPoint :: State Point blahblah
不知道有没有一个功能可以让
someFuncOverPoint
聚焦于Circle
:
someMagicFunc :: ??? -> State Point blahblah -> State Circle blahblah
也许这可以使用镜头来实现?
严格来说你可以。事实上,我们可以通过首先生成第一个
State Point a
来创建一个状态,然后将其传递到 State
中,所以:
someMagicFunc :: Double -> State Point a -> State Circle a
someMagicFunc r s = State (\s0 -> let ~(s1, a) = runState s s0 in (Circle s1 r, a))
所以这里我们构造一个
State
,它与一个函数一起使用,该函数将初始状态 s0
映射到下一个状态 s1
和结果,然后我们将其转换为一个以 Circle
作为状态的二元组,还有“结果”a
。
话虽如此,改变状态的类型有点奇怪。通常,状态类型在所有操作中保持相同。