我尝试使用fclabels更新一些旧代码,从v0.4更新为v2.0(lts-3.17),提升label
/ {{ 1}}到monad。旧代码是:
lens
所以我做的第一件事就是将{-# 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
函数的每个arg。
旧的fclabels使用setter函数来创建标签,该标签接受一个简单的值参数。 modify
函数用于创建更新的fclabels镜头,它使用现有值进行修改,我明白为什么它也会对monadic参数进行操作。
我需要为修改功能执行一些额外的管道工作,我发现modify
做了类似于我想要的事情,但我不清楚最好的方法是什么总的来说。
那么处理ap
函数的好方法是什么,所以我可以匹配预期的类型?
答案 0 :(得分:0)
为什么不用长篇大论来编写呢?
而不是试图用无点的方式一次性写出来?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
当然,如果你真的想要......那么你就可以对它进行编码 -