Claysley Arrow with a writer in Scala. Why doesn't it compile?

This is a continuation of my previous question . Looks like I still don't get it. Now I'm trying to compose functions that return the Writer monad.

scala> val f = {x: Int => Writer ("doing" + x + ";", x + 1)}
f: Int => scalaz.WriterT [scalaz.Id.Id, String, Int] = 

scala> Kleisli (f)> => Kleisli (f)
: 16: error: no type parameters for method apply: (f: A => M [B]) scalaz. Kleisli [M, A, B] in object Kleisli exist so that it can be applied to arguments (Int => scalaz .WriterT [scalaz.Id.Id, String, Int])
 --- because ---
argument expression type is not compatible with formal parameter type;
 found: Int => scalaz.WriterT [scalaz.Id.Id, String, Int]
 required:? A =>? M

              Kleisli (f)> => Kleisli (f)

Why doesn't it compile?

+3
source share
1 answer

When the Scala compiler expects a type similar to M[B], and you give it something like WriterT[Id, String, Int], it is unfortunately not smart enough to realize that you want to fix the first two type parameters and use the monad for WriterT[Id, String, _].

There are several possible ways around this limitation. The first is to define an alias of type:

type StringWriter[A] = WriterT[Id, String, A]

Now you can provide explicit type parameters (in fact, you can do this without an alias, but the lambdas type will make the line twice as long and ten times unreadable):

scala> Kleisli[StringWriter, Int, Int](f) >=> Kleisli[StringWriter, Int, Int](f)
res0: scalaz.Kleisli[StringWriter,Int,Int] = Kleisli(<function1>)

Scalaz , Miles Sabin "unapply trick" :

val ff = Kleisli.kleisliU(f) >=> Kleisli.kleisliU(f)

kleisliU Kleisli.apply, ( Unapply) , , WriterT[Id, String, Int].

+2

All Articles