【问题标题】:Functional lenses功能性镜片
【发布时间】:2012-01-08 14:13:15
【问题描述】:

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

【问题讨论】:

  • YouTube 上有 Edward Kmett 的 a nice introduction to lenses。这些示例在 Scala 中,但应该不难理解。
  • 是的,试着看那些,但是在我仍然保持警觉的同时有足够的时间,并不是那么容易:P
  • @Jochen:那里描述的镜头与这个问题所涉及的镜头没有太多共同之处。
  • 这里有很好的图片介绍:Lenses in Pictures.

标签: haskell functional-programming lenses


【解决方案1】:

一个镜头由两个函数组成,一个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)

【讨论】:

  • 您的撰写示例没有进行类型检查。 GHC 推断;镜头 a a -> 镜头 a a -> 镜头 a a
  • 大众:我不小心把fg翻了。
  • 它仍然没有在 a->c 中输入 check。它推断为 compose :: Lens a b -> Lens a a -> Lens a b
【解决方案2】:

查看问题lenses, fclabels, data-accessor - which library for structure access and mutation is better的答案 - 它对镜头有非常清楚的解释。

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

【讨论】:

    猜你喜欢
    • 2011-09-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-05-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多