我正在尝试使用fclabels将一些旧代码从v0.4更新到v2.0(lts -3.17),从而将label
/lens
提升为monad。旧的代码是:
{-# LANGUAGE TypeOperators #-}
import Data.Record.Label
import Control.Monad (liftM, liftM2)
liftMLabel :: Monad m => a :-> b -> m a :-> m b
liftMLabel l = label (liftM $ get l) (liftM2 $ set l)
因此,我要做的第一件事是将更label
改为lens
,并将set
其更改为modify
:
{-# LANGUAGE TypeOperators #-}
import Data.Label
import Control.Monad (liftM, liftM2)
liftMLabel :: Monad m => a :-> b -> m a :-> m b
liftMLens l = lens (liftM $ get l) (liftM2 $ modify l)
这产生了以下编译器错误:
Expected type: (m b -> m b) -> m a -> m a
Actual type: m (b -> b) -> m a -> m a
这很有意义,给出了如何liftM2
处理lens
modify
函数的每个参数。
旧的fclabels使用setter函数创建标签,该函数接受简单的value参数。该modify
函数,用于创建新fclabels镜头,对于需要使用现有的值修改功能,我明白为什么它也将在单子参数上操作。
我需要为Modify函数执行一些额外的工作,并且我发现这样ap
做的效果与我想要的类似,但是我不清楚总体上最好的方法是什么。
那么处理该modify
函数的一种好方法是什么,这样我就可以匹配期望的类型?
与其尝试以一种无意义的方式一次性全部编写,为什么不直接编写它呢?
liftMLens :: (Monad m) => a :-> b -> m a :-> m b
liftMLens l = lens (liftM $ get l) $ \f mx -> do
x <- mx
let v = get l x
v' <- f $ return v
return $ set l v' x
当然,如果您确实想这样做,则可以对其进行编码处理。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句