Как составить функции, которые возвращают 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)
скомпилировать с монадой трансформатор?
1 ответ
Writer[List[Int], ?]
действительно есть экземпляр монады - это всего лишь тот случай, когда скаляр не может увидеть это без небольшой помощи. Вы можете просто использовать 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
,