2015-11-15 23 views
4

單片眼鏡的自選具有以下訪問功能(Optional[C,A]):Monocle的選擇與部分鏡片一樣嗎?

getOption: C => Option[A] 
set: A => C => C 

這是在與(部分)非對稱透鏡數據的原始定義的賠率。我期望:

getOption: C => Option[A] 
setOption: A => C => Option[C] 

這是什麼原因?如何用Monocle獲得經典的部分鏡片?在對鏡頭進行編程時,我發現確保設置的整體性比得到更多的問題...

+0

Monocle在'Optional'上提供'setOption'方法,提供您正在查找的操作。如果沒有匹配,'set'只返回給定的'C'。 –

+0

那麼可選的setter可以來自一個可選的getter和一個完整的setter? –

+0

在檢查了'setOption'的源代碼之後,在我看來,它永遠不會產生'None',所以用這種方式製作一個部分透鏡似乎不可行,是嗎? –

回答

6

考慮以下部分鏡頭用於通過索引查找列表中的值(請注意,這僅僅是一個教學示例,因爲monocle.std.list.listIndex提供此功能現成的):

import monocle.Optional 

def listIndexOptional[A](i: Int): Optional[List[A], A] = 
    Optional[List[A], A](_.lift(i))(a => l => 
    if (l.isDefinedAt(i)) l.updated(i, a) else l 
) 

現在,我們可以定義一個Optional指向中的第三項字符串列表:

val thirdString = listIndexOptional[String](2) 

而且使用它像這樣:

scala> thirdString.set("0")(List("a", "b", "c")) 
res4: List[String] = List(a, b, 0) 

scala> thirdString.set("0")(List("a", "b")) 
res5: List[String] = List(a, b) 

請注意,如果沒有第三項,操作只是返回列表未修改。如果我們想知道該項目是否已經更新,我們可以使用setOption

scala> thirdString.setOption("0")(List("a", "b", "c")) 
res6: Option[List[String]] = Some(List(a, b, 0)) 

scala> thirdString.setOption("0")(List("a", "b")) 
res7: Option[List[String]] = None 

Optional.apply方法作爲其第二個參數,實際上是一個功能A => S => S部分是爲了方便,因爲我們經常要定義部分這樣,部分是因爲我們無法定義一個部分鏡頭,其中getOptionsetOption不同意目標是否存在。

如果您確實想要,您可以始終根據A => S => Option[S]定義一個Optional,最後加上getOrElse(s)

+0

('getOption','set')被選爲'Optional'的規範定義的另一個原因是'Iso','Prism','Lens'和'Optional'之間的菱形關係。 @puffnfresh製作了一個不錯的[圖](https://twitter.com/puffnfresh/status/654862731548446720)來展示這一點。 –

+0

謝謝!我明白。我誤解了setOption的實現。我現在可以看到它使用了修改和getOption,因此它只需發現合併是否已成功並失敗。我想我可以用這個:) –