importing specific typeclass syntax

60 views
Skip to first unread message

eric thul

unread,
May 18, 2013, 6:27:46 PM5/18/13
to sca...@googlegroups.com
hi All,

I have an example below that I am unsure how to get the imports right for the functionality I want to use.

There are three variations I have tried (among others but these are the main ones). Variation 1 and Variation 2 compile just fine. However, I thought Variation 3 would work, but I end up with the following compile error:

// Exiting paste mode, now interpreting.

<console>:65: error: value map is not a member of type parameter M[List[String]]
             b2 <- b1.map(b => testB.testB2(b)).sequenceU

So perhaps the compiler is not finding the functor ops? Perhaps I am missing an import for this to work?

Any suggestions or tips would be helpful.

Thanks,
 -Eric


PS - Example

import scalaz.Monad

// Variation 1 (works)
//import scalaz.syntax.all._

// Variation 2 (works)
import scalaz.syntax.{ToFunctorOps, ToMonadOps, ToTraverseOps}
object myimport extends ToFunctorOps with ToMonadOps with ToTraverseOps
import myimport._

// Variation 3 (does not work)
//import scalaz.syntax.monad._
//import scalaz.syntax.traverse._
//import scalaz.syntax.std.list._


import scalaz.std.list._

trait TestB[M[+_]] {
  implicit def M: Monad[M]

  def testB1: M[List[Int]]
  def testB2(i: Int): M[String]
}

trait TestA[M[+_]] {
  implicit def M: Monad[M]

  val testB: TestB[M]

  def testA: M[String] =
    for {
      b1 <- testB.testB1
      b2 <- b1.map(b => testB.testB2(b)).sequenceU
    } yield b2.mkString
}

Lars Hupel

unread,
May 20, 2013, 9:43:02 AM5/20/13
to sca...@googlegroups.com
Hi Eric,

> // Variation 2 (works)
> import scalaz.syntax.{ToFunctorOps, ToMonadOps, ToTraverseOps}
> object myimport extends ToFunctorOps with ToMonadOps with ToTraverseOps
> import myimport._

I wouldn't recommend that. As far as I am concerned, those traits are
not supposed to be extended by user code (maybe I'm wrong).

> // Variation 3 (does not work)
> //import scalaz.syntax.monad._
> //import scalaz.syntax.traverse._
> //import scalaz.syntax.std.list._

The problem is that you're both importing `monad` and `traverse` syntax.
Both extend the syntax for functors. Hence, ambiguity.

Here's a minimal example which fails:

import scalaz.Monad
import scalaz.syntax.monad._
import scalaz.syntax.traverse._

trait Foo[M[_]] {
implicit def M: Monad[M]
def mli: M[List[Int]]
def ms = mli.map(_.mkString)
}

// Exiting paste mode, now interpreting.

<console>:16: error: value map is not a member of type parameter
M[List[Int]]
def ms = mli.map(_.mkString)


... and here's how your code can be rewritten to make it work:

import scalaz._
import scalaz.syntax.monad._
import scalaz.std.list._

trait TestB[M[+_]] {
implicit def M: Monad[M]

def testB1: M[List[Int]]
def testB2(i: Int): M[String]
}

trait TestA[M[+_]] {
implicit def M: Monad[M]

val testB: TestB[M]

def testA: M[String] =
for {
b1 <- testB.testB1
b2 <- Traverse[List].sequence(b1.map(b => testB.testB2(b)))
} yield b2.mkString
}

OTOH, I think the best what you can do is to import all syntax.

eric thul

unread,
May 20, 2013, 1:26:19 PM5/20/13
to sca...@googlegroups.com
hi Lars,

Thank you for looking into this and finding a solution. I see the ambiguity issue you pointed out. I think I agree that importing all the syntax is the way to go here.

Thanks again.

Best,
 -Eric
Reply all
Reply to author
Forward
0 new messages