在下面的代码中,我的问题涉及到最高级的函数someFunc (下面的所有内容只是提供一个完整的示例)。我在那里使用了一个记录语法getter和fmap。实现someFunc的镜头方法是什么?
import Control.Lens
import Data.IntMap (IntMap)
someFunc :: Farm -> IntMap Size
someFunc farm =
_barnSize <$> farm ^. farmBarns
data Farm = Farm
{ _farmBarns :: IntMap Barn
}
farmBarns :: Lens' Farm (IntMap Barn)
farmBarns = lens _farmBarns (\farm barns -> farm { _farmBarns = barns } )
type Size = (Int, Int)
data Barn = Barn
{ _barnSize :: Size
}
barnSize :: Lens' Barn Size
barnSize = lens _barnSize (\barn size -> barn { _barnSize = size } )发布于 2016-11-14 16:05:45
只需将_barnSize替换为(^. barnSize)或等效的view barnSize
someFunc :: Farm -> IntMap Size
someFunc farm = view barnSize <$> farm ^. farmBarns对于"100%镜头“解决方案,您可以使用mapped设置器。不过,在这种情况下,我不认为这样做有任何真正的好处。
someFunc :: Farm -> IntMap Size
someFunc farm = (mapped %~ view barnSize) (farm ^. farmBarns)另一种可能的拼写是使用to将所有内容组合在一个getter中。这在这里也不会给你买多少钱,但是如果你想继续使用镜头样式的IntMap,通过链接额外的getter/folds/等等,可能会比较方便。
someFunc :: Farm -> IntMap Size
someFunc farm = farm ^. farmBarns . to (fmap (view barnSize))有一个特殊用途的组合器包含了上面的to/(^.)组合。它被称为views
someFunc :: Farm -> IntMap Size
someFunc farm = views farmBarns (fmap (view barnSize)) farm发布于 2016-11-14 19:42:32
在您的例子中,您可以使用mapped (或traversed)在可遍历的透镜上“映射”:
someFunc :: Farm -> IntMap Size
someFunc farm =
farm ^. farmBarns & mapped %~ view barnSize这可能有点令人困惑,但下面是正在发生的事情,我将添加括号以使其更清晰一些。
someFunc :: Farm -> IntMap Size
someFunc farm =
(farm ^. farmBarns) & (mapped %~ (view barnSize))基本上,我们用farm ^. farmBarns从农场得到IntMap Barns,在&的右边,我们用%~构造了一个设置器,它是over的中缀,但是over传递给目标的函数实际上只是用镜头聚焦barnSize。view barnSize :: Barn -> Size。
最后,我们使用&将其连接在一起,这相当于flip $,并从右手取出设置器,并在左手的结果上使用它。
https://stackoverflow.com/questions/40591051
复制相似问题