Объединение операций набора Scalaz Lens в цепочку

Пытаюсь освоить объективы scalaz7. Есть ли лучший способ связать операции набора?

case class Outer(left: Inner, right: Inner)
case class Inner(top: Int, bottom: Int)

val left = Lens.lensu[Outer, Inner](
    (o,v) => o.copy(left = v),
    _.left
)
val right = Lens.lensu[Outer, Inner](
    (o,v) => o.copy(right = v),
    _.right
)
val top = Lens.lensu[Inner, Int](
    (o,v) => o.copy(top = v),
    _.top
)

val leftTop = left >=> top
val rightTop = right >=> top

val outer0 = Outer(Inner(10,20), Inner(30, 40))
val outer1 = rightTop.set(leftTop.set(outer0, 11), 33)

Обновление:

У меня есть ощущение, что ответом может быть использование монады состояния, хотя я едва понимаю, почему это работает. Было бы интересно узнать, есть ли более аккуратный способ.

val modifier = for{
    _ <- leftTop := 11
    _ <- rightTop := 33
} yield Unit

modifier(outer0)._1   // = Outer(Inner(11,20),Inner(33,40))

person Pengin    schedule 15.12.2013    source источник


Ответы (1)


Вы можете несколько упростить версию монады State:

(leftTop := 11) >> (rightTop := 33) exec outer0

Или, если вы предпочитаете:

val modifier = (leftTop := 11) >> (rightTop := 33)
modifier.exec(outer0)

Ваша исходная версия State выглядит немного странно, поскольку <- в операторе for — это просто синтаксический сахар для вызовов .flatMap. Немного упрощая, результат leftTop := 11 имеет тип, подобный State[Outer, Outer, Int], что примерно эквивалентно функции с типом Outer => (Outer, Int). Состояние отслеживает часть Outer результата и передает часть Int в .flatMap. Поскольку вам не важен результат Int, вы присваиваете его _ и игнорируете.

>> делает то же самое, это .flatMap, который игнорирует свой аргумент и это то же самое, что писать:

(leftTop := 11) flatMap (_ => rightTop := 33)

Результатом этого является вычисление состояния, которое имеет вспомогательную функцию .exec, которая запускает вычисление с начальным состоянием (outer0) и возвращает конечное состояние (отбрасывая любой результат).

Если вы хотите избежать использования состояния, вам придется делать это так, как вы начали. Весь смысл State состоит в том, чтобы передавать промежуточные результаты между шагами, не упоминая их явно.

person Rev. C. Bennett Hoffman    schedule 17.01.2014