重载通用隐式转换

时间:2010-04-25 19:20:04

标签: scala polymorphism

我有一些隐式转换的scala(版本2.8.0RC1)问题。每当导入多个隐式转换时,第一个被隐藏。以下是问题出现的代码:

// containers
class Maybe[T]
case class Nothing[T]() extends Maybe[T]
case class Just[T](value: T) extends Maybe[T]

case class Value[T](value: T)

trait Monad[C[_]] {
  def >>=[A, B](a: C[A], f: A => C[B]): C[B]
  def pure[A](a: A): C[A]
}

// implicit converter
trait Extender[C[_]] {
  class Wrapper[A](c: C[A]) {
    def >>=[B](f: A => C[B])(implicit m: Monad[C]): C[B] = {
      m >>= (c, f)
    }

    def >>[B](b: C[B])(implicit m: Monad[C]): C[B] = {
      m >>= (c, { (x: A) => b } )
    }
  }

  implicit def extendToMonad[A](c: C[A]) = new Wrapper[A](c)
}

// instance maybe
object maybemonad extends Extender[Maybe] {
  implicit object MaybeMonad extends Monad[Maybe] {
    override def >>=[A, B](a: Maybe[A], f: A => Maybe[B]): Maybe[B] = {
      a match {
        case Just(x) => f(x)
        case Nothing() => Nothing()
      }
    }

    override def pure[A](a: A): Maybe[A] = Just(a)
  }
}

// instance value
object identitymonad extends Extender[Value] {
  implicit object IdentityMonad extends Monad[Value] {
    override def >>=[A, B](a: Value[A], f: A => Value[B]): Value[B] = {
      a match {
        case Value(x) => f(x)
      }
    }

    override def pure[A](a: A): Value[A] = Value(a)
  }
}

import maybemonad._
//import identitymonad._

object Main {
  def main(args: Array[String]): Unit = {
    println(Just(1) >>= { (x: Int) => MaybeMonad.pure(x) })
  }
}

当取消注释第二个import语句时,一切都会出错,因为第一个“extendToMonad”被镜像了。

然而,这个有效:

object Main {
  implicit def foo(a: Int) = new  {
    def foobar(): Unit = { 
      println("Foobar")
    }   
  }

  implicit def foo(a: String) = new  {
    def foobar(): Unit = { 
      println(a)
    }   
  }

  def main(args: Array[String]): Unit = { 
    1 foobar()
    "bla" foobar()
  }
}

那么,捕获量在哪里?我错过了什么?

此致 raichoo

2 个答案:

答案 0 :(得分:1)

实际上,绑定和导入的绑定会被名称遮蔽。这同样适用于导入的隐式转换。

我相信您可以在导入期间重命名为解决方法:

import IdentityMonad.{extendToMonad => extendToMonadIdentity}
import MaybeMonad.{extendToMonad => extendToMonadMaybe}

您可能希望查看Scalaz,特别是scalaz.{Functor, Scalaz, MA},以获取对这些类型类进行编码的其他方法。特别是,在搜索类型类Monad[X]时,会搜索伴随对象Monad

答案 1 :(得分:0)

我的猜测是编译器关注

implicit object IdentityMonad extends Monad[Value] 

更具体
implicit object MaybeMonad extends Monad[Maybe]

作为解决过程的一部分。丹尼尔发表了一篇文章,涵盖了这个问题here。在第二个示例中,调用直接按类型解析隐式,并且不需要上述解析规则。