82

有人可以向我解释功能性镜片吗?对于谷歌来说,这是一个令人惊讶的困难主题,我没有取得任何进展。我所知道的是,它们提供了与 OO 类似的获取/设置功能。

4

2 回答 2

62

镜头由两个函数组成,一个 getter 和一个 setter:

data Lens a b = Lens { getter :: a -> b, setter :: b -> a -> a }

例如,我们可能有一对镜片的第一部分和第二部分:

fstLens :: Lens (a, b) a
fstLens = Lens fst $ \x (a, b) -> (x, b)

sndLens :: Lens (a, b) b
sndLens = Lens snd $ \x (a, b) -> (a, x)

镜头的真正便利在于它们构成:

compose :: Lens b c -> Lens a b -> Lens a c
compose f g = Lens (getter f . getter g) $
                   \c a -> setter g (setter f c (getter g a)) a

他们机械地转换为State过渡:

lensGet :: MonadState s m => Lens s a -> m a
lensGet = gets . getter

lensSet :: MonadState s m => Lens s b -> b -> m ()
lensSet f = modify . setter f

lensMod :: MonadState s m => Lens s b -> (b -> b) -> m ()
lensMod f g = modify $ setter f =<< g . getter f

(+=) :: (MonadState s m, Num b) => Lens s b -> b -> m ()
f += x = lensMod f (+ x)
于 2011-11-29T14:31:26.477 回答
12

查看问题lens, fclabels, data-accessor的答案- 用于结构访问和突变的库更好- 它对镜头有非常清楚的解释。

此外,Data.Lensesfclabel库的文档提供了一些很好的使用示例。

于 2011-11-29T08:47:41.530 回答