Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/scala/16.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Scala 重载一组类型的函数_Scala_Implicit Conversion_Typeclass - Fatal编程技术网

Scala 重载一组类型的函数

Scala 重载一组类型的函数,scala,implicit-conversion,typeclass,Scala,Implicit Conversion,Typeclass,假设我想用以下方式为函数类型定义算术运算符,如()=>Int,()=>Double等 def + (a : () => Int, b : () => Int) = new (() => Int) { def apply() = a() + b() } 在为所有可能的参数类型组合定义类似函数时,是否有任何方法可以避免锅炉板代码? 这些类型可以是内置的(Int,Long,Double),用户定义的类型(如货币,数量等),以

假设我想用以下方式为函数类型定义算术运算符,如
()=>Int
()=>Double

def + (a : () => Int, b : () => Int) = 
      new (() => Int) { 
              def apply() = a() + b() 
      }
在为所有可能的参数类型组合定义类似函数时,是否有任何方法可以避免锅炉板代码? 这些类型可以是内置的(
Int
Long
Double
),用户定义的类型(如
货币
数量
等),以及
选项[T]
,其中
T
可以是前面提到的任何类型

def + (a : () => Option[Int], b : () => Double) = 
    new (() => Option[Double]) 
        {
            // this specific code could be factored out
            def apply() = 
                a() map { _ + b() }  
        }

您可以创建trait实例来定义特定类型操作的具体实现。然后要求将此特性作为操作的隐式参数,并调用这些具体实现


例如,检查源。

您可以创建实例来定义特定类型操作的具体实现。然后要求将此特性作为操作的隐式参数,并调用这些具体实现


例如,检查源。

在我看来,通过引入

trait PlusDefined[A,B] { 
    type Ret
    def plus(a : A, b : B) : Ret
}
以及为不同类型引入隐式值。我当前的解决方案无法避免所有锅炉板代码(如选项[t]的显式重载),但看起来可行:

import language.implicitConversions

trait Conversion[From, To]
{
    def convert(from : From) : To
}

object Conversions {

    implicit def toOption[T, U](implicit ev : Conversion[T,U]) 
                 : Conversion[T, Option[U]] =
        new Conversion[T, Option[U]]
        {
            def convert(x : T) = Some(ev.convert(x))
        }
    implicit def toOptionId[T] 
                 : Conversion[T, Option[T]] =
        new Conversion[T, Option[T]]
        {
            def convert(x : T) = Some(x)
        }
    implicit def betweenOptions[T, U](implicit ev : Conversion[T,U]) 
                 : Conversion[Option[T], Option[U]] =
        new Conversion[Option[T], Option[U]]
        {
            def convert(x : Option[T]) = x map { y => ev.convert(y) }
        }

    implicit val int2double     = 
        new Conversion[Int,  Double]{  def convert(x : Int) = x  }

    implicit val int2long       = 
        new Conversion[Int,  Long]  {  def convert(x : Int) = x  }

    implicit val long2double    = 
        new Conversion[Long, Double]{  def convert(x : Long) = x }

}

trait PlusDefined[A,B]
{
    type Ret
    def plus(a : A, b : B) : Ret
}

trait Addable_Level1 {
    implicit def rightConversion[A,B](implicit  c : Conversion[A,B], 
                                      ev : PlusDefined[B,B]) 
                 : PlusDefined[A,B] =
        new PlusDefined[A,B]
        {
            type Ret = PlusDefined[B,B]#Ret
            def plus(a : A, b : B) = ev.plus(c.convert(a), b)
        }

    implicit def leftConversion[A,B](implicit  c : Conversion[B,A], 
                                               ev : PlusDefined[A,A]) 
                 : PlusDefined[A,B] =
        new PlusDefined[A,B]
        {
            type Ret = PlusDefined[A,A]#Ret
            def plus(a : A, b : B) = ev.plus(a, c.convert(b))
        }
}

trait Addable_Level2  extends Addable_Level1
{
    implicit def rightOpt[A,B](implicit  ev : PlusDefined[A,B]) 
                 : PlusDefined[A,Option[B]] =
        new PlusDefined[A,Option[B]]
        {
            type Ret = Option[PlusDefined[A,B]#Ret]
            def plus(a : A, b : Option[B]) = b map { x =>  ev.plus(a,x) }
        }
    implicit def leftOpt[A,B](implicit  ev : PlusDefined[A,B]) 
                 : PlusDefined[Option[A],B] =
        new PlusDefined[Option[A],B]
        {
            type Ret = Option[PlusDefined[A,B]#Ret]
            def plus(a : Option[A], b : B) = a map { x =>  ev.plus(x,b) }
        }
    implicit def bothOpt[A,B](implicit  ev : PlusDefined[A,B]) 
                 : PlusDefined[Option[A],Option[B]] =
        new PlusDefined[Option[A],Option[B]]
        {
            type Ret = Option[PlusDefined[A,B]#Ret]
            def plus(a : Option[A], b : Option[B]) =
                (a,b) match {
                    case (Some(x), Some(y)) => Some(ev.plus(x,y))
                    case _ => None
                }
        }
}

object Addable extends Addable_Level2 {
    implicit def fromNumeric[T : Numeric] 
                 : PlusDefined[T,T] = new PlusDefined[T,T]
    {
        type Ret = T
        def plus(a : T, b : T) = implicitly[Numeric[T]].plus(a,b)
    }
}

在我看来,这个问题可以通过引入

trait PlusDefined[A,B] { 
    type Ret
    def plus(a : A, b : B) : Ret
}
以及为不同类型引入隐式值。我当前的解决方案无法避免所有锅炉板代码(如选项[t]的显式重载),但看起来可行:

import language.implicitConversions

trait Conversion[From, To]
{
    def convert(from : From) : To
}

object Conversions {

    implicit def toOption[T, U](implicit ev : Conversion[T,U]) 
                 : Conversion[T, Option[U]] =
        new Conversion[T, Option[U]]
        {
            def convert(x : T) = Some(ev.convert(x))
        }
    implicit def toOptionId[T] 
                 : Conversion[T, Option[T]] =
        new Conversion[T, Option[T]]
        {
            def convert(x : T) = Some(x)
        }
    implicit def betweenOptions[T, U](implicit ev : Conversion[T,U]) 
                 : Conversion[Option[T], Option[U]] =
        new Conversion[Option[T], Option[U]]
        {
            def convert(x : Option[T]) = x map { y => ev.convert(y) }
        }

    implicit val int2double     = 
        new Conversion[Int,  Double]{  def convert(x : Int) = x  }

    implicit val int2long       = 
        new Conversion[Int,  Long]  {  def convert(x : Int) = x  }

    implicit val long2double    = 
        new Conversion[Long, Double]{  def convert(x : Long) = x }

}

trait PlusDefined[A,B]
{
    type Ret
    def plus(a : A, b : B) : Ret
}

trait Addable_Level1 {
    implicit def rightConversion[A,B](implicit  c : Conversion[A,B], 
                                      ev : PlusDefined[B,B]) 
                 : PlusDefined[A,B] =
        new PlusDefined[A,B]
        {
            type Ret = PlusDefined[B,B]#Ret
            def plus(a : A, b : B) = ev.plus(c.convert(a), b)
        }

    implicit def leftConversion[A,B](implicit  c : Conversion[B,A], 
                                               ev : PlusDefined[A,A]) 
                 : PlusDefined[A,B] =
        new PlusDefined[A,B]
        {
            type Ret = PlusDefined[A,A]#Ret
            def plus(a : A, b : B) = ev.plus(a, c.convert(b))
        }
}

trait Addable_Level2  extends Addable_Level1
{
    implicit def rightOpt[A,B](implicit  ev : PlusDefined[A,B]) 
                 : PlusDefined[A,Option[B]] =
        new PlusDefined[A,Option[B]]
        {
            type Ret = Option[PlusDefined[A,B]#Ret]
            def plus(a : A, b : Option[B]) = b map { x =>  ev.plus(a,x) }
        }
    implicit def leftOpt[A,B](implicit  ev : PlusDefined[A,B]) 
                 : PlusDefined[Option[A],B] =
        new PlusDefined[Option[A],B]
        {
            type Ret = Option[PlusDefined[A,B]#Ret]
            def plus(a : Option[A], b : B) = a map { x =>  ev.plus(x,b) }
        }
    implicit def bothOpt[A,B](implicit  ev : PlusDefined[A,B]) 
                 : PlusDefined[Option[A],Option[B]] =
        new PlusDefined[Option[A],Option[B]]
        {
            type Ret = Option[PlusDefined[A,B]#Ret]
            def plus(a : Option[A], b : Option[B]) =
                (a,b) match {
                    case (Some(x), Some(y)) => Some(ev.plus(x,y))
                    case _ => None
                }
        }
}

object Addable extends Addable_Level2 {
    implicit def fromNumeric[T : Numeric] 
                 : PlusDefined[T,T] = new PlusDefined[T,T]
    {
        type Ret = T
        def plus(a : T, b : T) = implicitly[Numeric[T]].plus(a,b)
    }
}

您能提供更多您正在谈论的用户定义类的示例吗?您是否暗示对它们有一些限制(例如,带有一个参数的case类等)?否则我猜范围太广了。我也不知道你到底想做什么,但听起来你可能是在从scalaz中重新发明一些东西。首先,你可以去掉
new
样板:
def+(a:()=>Int,b:()=>Int=>a()+b()
事实上,我不想对要支持的用户定义类型施加限制(但显然它们将是带有一个参数的case类)。我想在引入类型类的基础上找到一个解决方案,比如
trait-hascovertion[From,to]{def-convert(x:From):to}
trait-Addable[T]{def-plus(x:T,y:T):T}
,但我不知道如何让它们协同工作。你能提供更多你正在谈论的用户定义类的例子吗?您是否暗示对它们有一些限制(例如,带有一个参数的case类等)?否则我猜范围太广了。我也不知道你到底想做什么,但听起来你可能是在从scalaz中重新发明一些东西。首先,你可以去掉
new
样板:
def+(a:()=>Int,b:()=>Int=>a()+b()
事实上,我不想对要支持的用户定义类型施加限制(但显然它们将是带有一个参数的case类)。我想在引入类型类的基础上找到一个解决方案,比如
trait hascovertion[From,to]{def convert(x:From):to}
trait Addable[T]{def plus(x:T,y:T):T}
但我不知道如何让它们一起工作。谢谢,但我觉得scala.math.Numeric和Spire不能解决混合算术的问题谢谢,但我觉得scala.math.Numeric和Spire不能解决混合算术的问题