Пример Государственной и Свободной монады в Скалазе

Может кто-нибудь привести пример использования ScalaZ Free monad?

Например, если у меня есть простая функция State и я хочу применить ее 10 000 раз, я получу StackruError:

def setS(i: Int) :State[List[Int], Unit] = State { l => ( i::l, () ) }

val state = (1 to 10000).foldLeft( put(Nil :List[Int]) ) {
    case (st, i) => st.flatMap(_ => setS(i))
}

state(Nil)

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

1 ответ

Решение

Как я уже сказал в комментарии выше, снятие State вычисления в StateT[Free.Trampoline, S, A] Кажется, это должно работать:

import scalaz._, Scalaz._, Free.Trampoline

def setS(i: Int): State[List[Int], Unit] = modify(i :: _)

val s = (1 to 10000).foldLeft(state[List[Int], Unit](()).lift[Trampoline]) {
  case (st, i) => st.flatMap(_ => setS(i).lift[Trampoline])
}

s(Nil).run

К сожалению, это все еще переполняет стек, но, как отмечает Дейв Стивенс, последовательность с аппликативным *> вместо flatMap устраняет проблему:

val s = (1 to 100000).foldLeft(state[List[Int], Unit](()).lift[Trampoline]) {
  case (st, i) => st *> setS(i).lift[Trampoline]
}

s(Nil).run

Я не уверен, почему это так, и я задал новый вопрос конкретно о разнице, но это должно помочь вам начать с Free,

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