pat*_*pat 4 haskell haskell-lens
在中Control.Lens.Lens,有一个功能
modifying :: MonadState s m => ASetter s s a b -> (a -> b) -> m ()
Run Code Online (Sandbox Code Playgroud)
这允许MonadState通过纯函数来变换状态下的镜头下的值(a -> b)。
但是,我们可能希望允许transform函数失败m,要求它具有type (a -> m b)。
我在镜头库中浏览了此功能,但找不到,因此实现了:
modifyingM l f = use l >>= f >>= assign l
Run Code Online (Sandbox Code Playgroud)
哪个可以解决问题,但我想知道镜头库中是否已经存在可以执行此操作的功能。
我没看到那样的东西。ASetter被定义为
type ASetter s t a b = (a -> Identity b) -> s -> Identity t
Run Code Online (Sandbox Code Playgroud)
因此它的功能不足以胜任这项工作(Setter也无法做到)。另一方面,结果表明a Lens比必需的要强一些。那么,让我们考虑如何使用Traversal。
type Traversal s t a b =
forall f. Applicative f => (a -> f b) -> s -> f t
Run Code Online (Sandbox Code Playgroud)
所以
Traversal s s a b =
forall f. Applicative f => (a -> f b) -> s -> f s
Run Code Online (Sandbox Code Playgroud)
Applicative我们要哪一个?m似乎是显而易见的尝试。当我们通过遍历时a -> m b,我们会返回s -> m s。大!像往常一样lens,我们实际上只需要用户提供ATraversal,我们就可以克隆它。
modifyingM
:: MonadState s m
=> ATraversal s s a b
-> (a -> m b) -> m ()
modifyingM t f = do
s <- get
s' <- cloneTraversal t f s
put s'
Run Code Online (Sandbox Code Playgroud)
很好,因为它仅遍历状态一次。
的确,即使那样也太过分了。最自然的是
modifyingM
:: MonadState s m
=> LensLike m s s a b
-> (a -> m b) -> m ()
modifyingM t f = do
s <- get
s' <- t f s
put s'
Run Code Online (Sandbox Code Playgroud)
您可以直接应用,为一Traversal,Lens,Iso,或Equality,或使用cloneTraversal,cloneLens,cloneIso,或(在lens-4.18或更高版本)cloneEquality,将其应用到单态的变种。
| 归档时间: |
|
| 查看次数: |
93 次 |
| 最近记录: |