[英]Composition of partial lenses
我试图找出最简洁的方法来修改嵌套在Maybe
类型(或其他类型的建模偏好)内的值。
以下是示例设置:
{-# LANGUAGE TemplateHaskell #-}
import Control.Lens
data Outer = Outer { _inner :: Maybe Inner }
deriving (Show)
data Inner = Inner { _foo :: Int }
deriving (Show)
makeLenses ''Outer
makeLenses ''Inner
使用lens
以一种有点混乱的方式很容易做到这一点:
wibble :: Outer -> Maybe Outer
wibble o = do i <- view inner o
let i' = over foo succ i
return $ set inner (Just i') o
为了说明为什么这是令人讨厌的,这是我想要写的:
wibble' :: Outer -> Maybe Outer
wibble' = overish inner.foo succ
overish = ???
查找字段失败应该只是使整个操作失败,而不是让我在可能发生的每个点上明确地检查失败。
有什么建议么? 我试过导航各种lens
模块,但似乎没有任何东西适合这个法案。
您可以使用over (inner.traverse.foo)
写入嵌套字段。 这不会以您想要的方式报告失败,因为它成功映射了所有0个目标。
traverse
(来自Data.Traversable
,由Control.Lens
重新导出),这里为您提供Traversal
Maybe
的Traversal
。
您可以使用(^?)
读取它以查看镜头的目标是否存在。
我们可以通过使用现有的镜头组合器分别进行读写来解决这个问题,但我们可以直接构建这样的组合器:
import Data.Monoid (Any(..))
import Control.Monad (guard)
overish :: LensLike ((,) Any) s t a b -> (a -> b) -> s -> Maybe t
overish l f s = case l (\a -> (Any True, f a)) s of
(Any r, t) -> t <$ guard r
你可以用l %%~ \\a -> (Any True, fa)
来写这个。
您可以使用nullOf
轻松检查Traversal
是否没有目标,但这需要两次传递和更高级别的类型:
overish :: Traversal s t a b -> (a -> b) -> s -> Maybe t
overish l f s = over l f s <$ guard (not (nullOf l s))
这实际上只是检查是否有目标,然后在有目标的情况下将setter应用于它。
然后你可以使用
overish (inner.traverse.foo) succ
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.