Applicative vs. monadic combinators and the free monad in Scalaz

后端 未结 3 1316
醉酒成梦
醉酒成梦 2020-12-31 11:55

A couple of weeks ago Dragisa Krsmanovic asked a question here about how to use the free monad in Scalaz 7 to avoid stack overflows in this situation (I\'ve adapted his code

3条回答
  •  难免孤独
    2020-12-31 12:23

    Mandubian is correct, the flatMap of StateT doesn't allow you to bypass stack accumulation because of the creation of the new StateT immediately before calling the wrapped monad's bind (which would be a Free[Function0] in your case).

    So Trampoline can't help, but the Free Monad over the functor for State is one way to ensure stack safety.

    We want to go from State[List[Int],Unit] to Free[a[State[List[Int],a],Unit] and our flatMap call will be to Free's flatMap (that doesn't do anything other than create the Free data structure).

    val s = (1 to 100000).foldLeft( 
        Free.liftF[({ type l[a] = State[List[Int],a]})#l,Unit](state[List[Int], Unit](()))) {
          case (st, i) => st.flatMap(_ => 
              Free.liftF[({ type l[a] = State[List[Int],a]})#l,Unit](setS(i)))
        }
    

    Now we have a Free data structure built that we can easily thread a state through as such:

    s.foldRun(List[Int]())( (a,b) => b(a) )
    

    Calling liftF is fairly ugly so I have a PR in to make it easier for State and Kleisli monads so hopefully in the future there won't need to be type lambdas.

    Edit: PR accepted so now we have

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

提交回复
热议问题