如何将 fclabels 镜头提升到 Monad?
How can I lift an fclabels Lens to a Monad?
我正在尝试使用 fclabels, from v0.4 to 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 函数来创建标签,它接受一个简单的值参数。 modify
函数,用于创建更新的 fclabels 镜头,接受一个使用现有值进行修改的函数,我明白了为什么它也会对单子参数进行操作。
我需要为修改函数执行一些额外的管道,我看到 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
当然,如果你真的想,你可以用代码打高尔夫球...
我正在尝试使用 fclabels, from v0.4 to 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 函数来创建标签,它接受一个简单的值参数。 modify
函数,用于创建更新的 fclabels 镜头,接受一个使用现有值进行修改的函数,我明白了为什么它也会对单子参数进行操作。
我需要为修改函数执行一些额外的管道,我看到 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
当然,如果你真的想,你可以用代码打高尔夫球...