arya
arya

Reputation: 956

type parameter inference + higher order types + type classes = :-(

import scalaz._; import Scalaz._

def foo[M[_]:MonadPlus,A](a:A) = a.point[M]
// foo: [M[_], A](a: A)(implicit evidence$1: scalaz.MonadPlus[M])M[A]

def bar1[M[_]:MonadPlus](i:Int): M[Int] = 
  foo(i) // <-- error: ambiguous implicit values

// this works, but why?  Isn't it just the same?
def bar2[M[_]:MonadPlus](i:Int): M[Int] = 
  foo(i)(implicitly[MonadPlus[M]])

def bar3[M[_]](i:Int)(implicit m:MonadPlus[M]): M[Int] = 
  foo(i)(m) // slightly less surprising that this works

def bar4[M[_]:MonadPlus](i:Int): M[Int] = 
  foo[M,Int](i) // this also works, but why?

build.sbt:

scalaVersion := "2.9.2"

libraryDependencies += "org.scalaz" %% "scalaz-core" % "7.0.0-M5"

(although I get the same result in 2.10.0-RC3)

Upvotes: 4

Views: 210

Answers (1)

Eric
Eric

Reputation: 15557

You get the same error message if you simply write:

import scalaz._; import Scalaz._

def foo[M[_]:MonadPlus,A](a:A) = a.point[M]

foo(1) // <-- error: ambiguous implicit values
       // both value listInstance ...
       // and value optionInstance ...

My understanding is that the compiler tries to typecheck the "body" of the bar1 method and without considering that there may be a MonadPlus[M] instance in scope (brought by the bar definition), it already finds 2 specific MonadPlus[M] instances (listInstance and optionInstance) which are suitable for a foo invocation. At this stage it just declares an ambiguity.

Then in bar2 and bar3 you specify explicitly the instance to use and in bar4 you give the type parameters which are M and Int which is not ambiguous on the foo call because the only implicit in scope with these constraints is implicitly[MonadPlus[M]].

Upvotes: 2

Related Questions