I am trying to developp a generic logger with OptionT.monadTell
So far, it looks (at least for me!) not so bad :
import scalaz._
import Scalaz._
object LoggerOption {
def Logger[M:Monoid,A] = OptionT.monadTell[Writer,M,A]
def Write[M:Monoid,A](l : M , oi : Option[A]) = oi match {
case Some(i) => Logger[M,A].writer(l,i)
case None => Logger[M,A] tell l flatMap { _ => Logger[M,A].none[A] }
}
}
I can do things like these :
println(LoggerOption.Write(List("No Int"),none:Option[Int]).run.run)
println(LoggerOption.Write(List("Some Int"),Some(6)).run.run)
println(LoggerOption.Write("No Char",none:Option[Char]).run.run)
println(LoggerOption.Write(8,Some('a')).run.run)
and even :
sealed trait ErrorLevel
case object INFO extends ErrorLevel
case object WARNING extends ErrorLevel
case object FATAL extends ErrorLevel
case class MyError (val Level : ErrorLevel, val Message : String)
def dummy(i : Int) = if ( i < 0) LoggerOption.Write(List(MyError(FATAL,"Negative number provided")),none:Option[Int]) else
if (i % 2 == 0) LoggerOption.Write(List(MyError(INFO,"Some even Int provided")),Some(i)) else
LoggerOption.Write(List(MyError(WARNING,"Some odd Int provided => Incremented")),Some(i+1))
println(dummy(-1).run.run)
println(dummy(6).run.run)
println(dummy(5).run.run)
So far so good.
Now let's consider those two lists :
val lnok = List(2,3,-1,4)
val lok = List(0,5,6)
I traversing them with dummy should produce a Writer with written-part being a List accumulating all the logs and value-part a Option[List[Int]] accumulating all the results :
println(lnok.traverseU(dummy(_)))
println(lok.traverseU(dummy(_)))
But it doesn't compile :
Unable to unapply type `scalaz.OptionT[[+α]scalaz.Writer[List[Test.MyError],α],Int]` into a type constructor of kind `M[_]` that is classified by the type class `scalaz.Applicative`
1) Check that the type class is defined by compiling `implicitly[scalaz.Applicative[<type constructor>]]`.
2) Review the implicits in object Unapply, which only cover common type 'shapes'
(implicit not found: scalaz.Unapply[scalaz.Applicative, scalaz.OptionT[[+α]scalaz.Writer[List[Test.MyError],α],Int]])
println(lnok.traverseU(dummy(_)))
^
It seems that something is missing in Unapply.scala. I first assumed that something was wrong with the class MyError, but I get the same messages if I use a simple string.
Any idea?
Thanks
Benoit
PS : Feel free to give your advice on the whole code!