Usually Scalaz's Unapply
does a pretty good job, but it seems to break down here with traverseU
:
scala> import scalaz._, Scalaz._, Unapply._
import scalaz._
import Scalaz._
import Unapply._
scala> val stateMonadInstance = unapplyMAB2[Monad, State, Int, Unit](IndexedStateT.stateMonad[Int]).TC
stateMonadInstance: scalaz.Monad[[X]scalaz.IndexedStateT[[+X]X,Int,Int,X]] = scalaz.StateTInstances1$$anon$1@27c591e1
scala> List(1, 2, 3).traverseU((i: Int) => stateMonadInstance.pure(i))
<console>:18: error: Unable to unapply type `scalaz.IndexedStateT[[+X]X,Int,Int,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.IndexedStateT[[+X]X,Int,Int,Int]])
List(1, 2, 3).traverseU((i: Int) => stateMonadInstance.pure(i))
^
The traverseS
method seems to have been created as a workaround for this problem, whatever it is:
scala> List(1, 2, 3).traverseS((i: Int) => stateMonadInstance.pure(i))
res11: scalaz.State[Int,List[Int]] = scalaz.package$State$$anon$3@2634d0e2
But I'm trying to write a library which is generic with respect to the monad in question, so that's not a very good fit. Does anyone know what the exact problem is here that's preventing this from working, and if there's a workaround which doesn't require special-casing for State
?
Ok, this works:
scala> import scalaz._, Scalaz._, Unapply._
import scalaz._
import Scalaz._
import Unapply._
scala> val unapply = unapplyMAB2[Monad, State, Int, Unit](IndexedStateT.stateMonad[Int])
unapply: scalaz.Unapply[scalaz.Monad,scalaz.State[Int,Unit]]{type M[X] = scalaz.State[Int,X]; type A = Unit} = scalaz.Unapply_0$$anon$13@53a6f572
scala> List(1, 2, 3).traverseU((i: Int) => unapply.TC.pure(i))
res0: scalaz.IndexedStateT[scalaz.Id.Id,Int,Int,List[Int]] = scalaz.IndexedStateT$$anon$10@737c45ee
In fact just regular old traverse
works in this case:
scala> List(1, 2, 3).traverse((i: Int) => unapply.TC.pure(i))
res1: unapply.M[List[Int]] = scalaz.IndexedStateT$$anon$10@73c622ec
I suppose what's going on is that I need to have the Unapply
instance in scope in order to know what types the TC
field is referring to.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With