具有镜头的MonadState中的子计算

时间:2018-01-14 22:31:44

标签: haskell state-monad

是否可以创建一个函数:

liftState :: (MonadState s ms, MonadState t mt) => Lens' s t -> mt a -> ms a

如果Lens' s t可以在t内获取并设置s,则会将状态MonadState的{​​{1}}计算提升为t 1}}使用状态MonadState进行计算?

如何在不同的州类型上运行子计算?

1 个答案:

答案 0 :(得分:3)

一般说明:使用Lens / Getter / Prism'等作为函数的参数类型很少是个好主意。请记住,那些是真正普遍量化的类型(在lens,Van Laarhoven类型∀ f . (a -> f b) -> s -> f t),因此接受它们的函数是rank-2多态,这对于类型检查器来说是相当痛苦的。相反,您应该使用其中一个具体的光学类型,它们位于lens库中,前缀为字母A。即你想成功吗

liftState :: (MonadState s ms, MonadState t mt) => ALens' s t -> mt a -> ms a

虽然duplode已经评论过你应该真的只使用zoom,但是自己实现这个不太通用的版本也不难:

liftState l m = state $ \s -> case runState m $ s ^# l of
                           (a, b) -> (a, s & l #~ b)

此处,^# and #~与知名度较高的^..~运算符基本相同,但实际上分别需要AGetterASetter的运算符除外。 (与Lens'兼容,但与ALens'不兼容;在更复杂的功能中,您可以使用cloneLens)来解决此问题。