2015-11-15 8 views
4

OPTIONALS монокле имеет следующие функции доступа (для Optional[C,A]):Возможны ли опции Monocle так же, как частичные линзы?

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

Это вступает в противоречии с первоначальным определением (частичными) асимметричных линз данных. Я бы ожидал:

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

В чем причина этого? Как получить классические частичные линзы с помощью Monocle? При программировании линз я обнаружил, что гораздо более проблематично обеспечить совокупность множества, чем получить ...

+0

Monocle предоставляет метод 'setOption' на' Optional', который обеспечивает операцию, которую вы ищете. 'set' просто возвращает данный' C' unmodified, если нет совпадения. –

+0

Так может быть и дополнительный сеттер, выводимый из дополнительного геттера и общего сеттера? –

+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 частично является удобство, так как мы часто хотим определить частичный таким образом, и частично, чтобы мы не могли определить частичную линзу, где getOption и setOption не согласны с тем, существует ли цель.

Если вы действительно этого хотите, вы всегда можете определить Optional с точки зрения установщика A => S => Option[S], наклеив на конец getOrElse(s).

+0

Другая причина, по которой ('getOption',' set') была выбрана как каноническое определение «Необязательно» - это отношение алмазов между «Iso», «Prism», «Lens» и «Optional». @puffnfresh сделал хороший [диаграмма] (https://twitter.com/puffnfresh/status/654862731548446720), чтобы показать это. –

+0

Спасибо! Я понимаю. Я неправильно понял внедрение setOption. Теперь я вижу, что он использует модификацию и getOption, поэтому у него есть все необходимое, чтобы выяснить, удалось ли слияние и не удалось. Я думаю, что смогу с этим справиться :) –