Как составить функции, возвращающие Writer [List [Int], Int]?

Предположим, у меня есть несколько функций Int => Int, составленных из andThen:

val f1: Int => Int = _ + 1
val f2: Int => Int = _ + 2
val f3: Int => Int = _ + 3

val f = f1 andThen f2 andThen f3

Теперь мне нужно вернуть и промежуточные результаты. Поэтому я могу преобразовать все эти функции в Int => (List[Int], Int), где список содержит аргументы.

Я, вероятно, могу использовать Writer[List[Int], Int] из scalaz для представления пары (List[Int], Int):

val fw1: Int => Writer[List[Int], Int] = x => f1(x).set(List(x))
val fw2: Int => Writer[List[Int], Int] = x => f2(x).set(List(x))
val fw3: Int => Writer[List[Int], Int] = x => f3(x).set(List(x))

Чтобы составить fw1, fw2 и fw3, мне, вероятно, нужно обернуть их Kleisli. Однако Kleisli(fw1) не компилируется, поскольку Writer[List[Int], Int] не монада.

Я предполагаю, что мне, вероятно, понадобится monad transformer, чтобы сделать Writer[List[Int], Int] монаду, но я точно не знаю, как это сделать. Итак, мой вопрос: как заставить Kleisli(fw1) компилироваться с преобразователем монад?


person Michael    schedule 28.08.2015    source источник


Ответы (1)


У Writer[List[Int], ?] есть экземпляр монады - это как раз тот случай, когда scalac не может этого увидеть без небольшой помощи. Вы можете просто использовать kleisliU, что похоже на Kleisli.apply, но с некоторой помощью по выводу типа из Unapply (который описан здесь и в ряде других мест):

import scalaz._, Scalaz._, Kleisli.kleisliU

val f1: Int => Int = _ + 1
val f2: Int => Int = _ + 2
val f3: Int => Int = _ + 3

val fw1: Int => Writer[List[Int], Int] = x => f1(x).set(List(x))
val fw2: Int => Writer[List[Int], Int] = x => f2(x).set(List(x))
val fw3: Int => Writer[List[Int], Int] = x => f3(x).set(List(x))

val f = kleisliU(fw1) andThen kleisliU(fw2) andThen kleisliU(fw1)

А потом:

scala> f.run(10)
res0: scalaz.WriterT[[+X]X,List[Int],Int] = WriterT((List(10, 11, 13),14))

Вы также можете указать явные параметры типа для Kleisli.apply или Kleisli.kleisli.

person Travis Brown    schedule 28.08.2015
comment
Спасибо за ответ и напоминание о Unapppy. Может, в этот раз я попробую пощупать его. - person Michael; 28.08.2015