Являются ли опции Monocle такими же, как частичные линзы?

Опции Monocle имеют следующие функции доступа (для Optional[C,A]):

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

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

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

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

1 ответ

Решение

Рассмотрим следующую частичную линзу для поиска значений в списке по индексу (обратите внимание, что это всего лишь педагогический пример, так как 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) в конце.

Другие вопросы по тегам