如何撰写"可能"镜头?

Sau*_*nda 2 haskell haskell-lens

如果我有一个嵌套记录的镜头,每个镜头返回一个Maybe,我怎么能让它们组成,所以如果"遍历"中的任何内容返回一个Nothing最后的结果是Nothing

data Client = Client
  {
    clientProperties :: Maybe Properties
  , ...
  }

data Properties = Properties
  {
    propSmtpConfig :: Maybe SmtpConfig
  , ...
  }

c :: Client 
c = undefined

smtp = c ^. (properties . smtpConfig) -- How to make these lenses compose?
Run Code Online (Sandbox Code Playgroud)

编辑我尝试了很多选项,但这是我能想到的最好的选择.寻找更清洁的东西:

(client ^. properties) >>= (view smtpConfig)
Run Code Online (Sandbox Code Playgroud)

Rei*_*chs 7

你可以使用_Just棱镜.这是一个人为的例子:

> (Just (Just 1, ()), ()) & _1 . _Just . _1 . _Just +~ 1
(Just (Just 2,()),())
Run Code Online (Sandbox Code Playgroud)

在你的情况下,我想你想要

properties . _Just . smtpConfig . _Just
Run Code Online (Sandbox Code Playgroud)


Gur*_*las 3

client ^? properties . _Just . smtpConfig . _Just
Run Code Online (Sandbox Code Playgroud)

编辑:像镜头这样的光学器件可以将小动作变成大动作。光学合成是函数合成。_Just将 上的动作 变为a上的动作Maybe a。镜头可以将小的读取动作变成大的读取动作,将小的写入动作变成大的写入动作,但_Just无法处理读取动作,因为在a中Nothing没有a。因此,_Just它是比透镜弱的光学器件,即遍历。组合光学器件始终可以准确地执行所有部件都可以执行的操作。因此properties . _Just . smtpConfig . _Just是一个遍历。(^?)使用遍历可以使用的读取操作的变体:“也许读取一个值”。因此上面这行代码将微不足道的成功阅读动作变成Just :: SmtpConfig -> Maybe SmtpConfig了大型阅读动作Client -> Maybe SmtpConfig