带泛型类型的默认函数参数

时间:2017-09-10 05:58:21

标签: scala generics default-value

我的函数获取另一个函数(将输入类型映射到输出类型)作为参数:

type Handled[S,R] = S => R

def myFunc[S,R](value: S, handled: Handled[S,R] = defaultHandled): R = {
  handled(value)
}

我需要编写defaultHandled函数,它将获取输入类型并按原样返回。

所以默认情况下我想将输入类型映射到输出类型,其中输入类型与输出类型相同。此函数应该简单地将输入传递给任何输入类型的输出。 怎么做?

3 个答案:

答案 0 :(得分:5)

虽然从技术上说这是可能的:

type Handled[S, R] = S => R

def defaultHandled[S, R](x: S): R = x.asInstanceOf[R]

def myFunc[S, R](value: S, handled: Handled[S, R] = defaultHandled[S, R] _): R = {
  handled(value)
}

myFunc[Int, Int](1)

这不是类型安全的,通常不是一个好主意。例如,如果您尝试使用不同的类型参数调用myFunc,同时仍然依赖于默认的handled值,那么您将获得运行时异常:

myFunc[Int, String](1)

java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.String

Scala解决此问题的方法是将其作为隐式参数处理。在这种情况下,您可以提供默认实现,编译器将使用它。

type Handled[S, R] = S => R

implicit def defaultHandled[S]: Handled[S, S] = identity

def myFunc[S, R](value: S)(implicit handled: Handled[S, R]): R = {
  handled(value)
}

myFunc(1) // compiles and works

myFunc[Int, String](1) // compilation error: Error:(11, 21) No implicit view 
                       // available from Int => String.
                       //myFunc[Int, String](1)
                       //            ^

答案 1 :(得分:2)

我会说,对于这个特定情况,有一个简单的解决方案可以实现您想要的结果:只需用重载替换默认参数。

type Handled[S,R] = S => R

def myFunc[S,R](value: S, handled: Handled[S,R]): R = {
  handled(value)
}

def myFunc[S](value: S): S = value

答案 2 :(得分:0)

如果SR是两种任意类型(不相互依赖),那么我想这是不可能的(没有运行时转换)。您应为每defaultHandledS提供R。对于任意s => sS => S的类型为S => R,而非R

但如果类型R 取决于类型 S,那么您可以考虑执行以下操作:

  trait Handled[S] {
    type R
    def apply(s: S): R
  } 
  object Handled {
    type Aux[S, R0] = Handled[S] {type R = R0}
    def apply[S, R0](f: S => R0): Aux[S, R0] = new Handled[S] {
      override type R = R0
      override def apply(s: S): R = f(s)
    }
  }


  def myFunc[S](value: S, handled: Handled[S] = Handled[S, S](s => s)): handled.R = {
    handled(value)
  }

此处Handled[S](与Handled.Aux[S, R]相反)是existential type