简体   繁体   English

将参数函数指定为输入,而不会在Scala中过度约束它们

[英]Specify parametric functions as inputs without overly constraining them in Scala

I've backed myself into an interesting corner while designing a higher order typed interface. 在设计更高阶的类型化界面时,我将自己置于一个有趣的角落。

I want to do something like this 我想做这样的事情

trait SomeTrait {
  def higherOrder(f: (Int, A) => List[A]): String
}

object SomeImple extends SomeTrait {
  def higherOrder(f: (Int, A) => List[A]): String = {
    f(3, "HI").mkString(", ") + f(3, 7).mkString(", ")
  }
}

I want to specify that a function takes another higher order function as input that works for any type (in this case A ). 我想指定一个函数将另一个更高阶的函数用作任何类型的输入(在这种情况下为A )。 For instance: 例如:

def someFun[A](n: Int, a: A): List[A] =
  if (n <= 0) {
    List.empty
  } else {
    a :: (someFun(n - 1, a))
  }

However If a add a type parameter to the higherOrder that means the function f can only be used at one type. 但是,如果在higherOrder中添加类型参数,则意味着函数f只能在一种类型上使用。 Is there a way to take parametric functions as inputs without overly constraining them? 有没有一种方法可以将参数函数作为输入而又不过度限制它们呢?

You can't parameterize a function like that, but you can parameterize a method: 您不能像这样对函数进行参数化,但是可以对方法进行参数化:

trait SomeTrait {
  def higherOrder(fn: {def apply[A](n: Int, a: A): List[A]}): String
}

object SomeImple extends SomeTrait {
  def higherOrder(f: {def apply[A](n: Int, a: A): List[A]}): String = {
    f(3, "HI").mkString(", ") + f(3, 7).mkString(", ")
  }
}

object someFun {
  def apply [A] (n: Int, a: A): List[A] = {
    if (n <= 0) {
      List.empty
    } else {
      a :: (someFun(n - 1, a))
    }
  }
}

Using a structural type (or you can create a trait that can be implemented by the type holding the method), you can request the method take a type param. 使用结构类型(或者您可以创建可以由保存该方法的类型实现的特征),可以请求该方法采用类型参数。

Unfortunately, you have to wrap it in an object (or some class) because a regular method can only be "lifted" to a Function and a Function 's type parameters are fixed at definition time. 不幸的是,您必须将其包装在一个对象(或某个类)中,因为常规方法只能“提升”到FunctionFunction的类型参数在定义时是固定的。

For reference: https://gist.github.com/jdegoes/97459c0045f373f4eaf126998d8f65dc#polymorphic-functions 供参考: https : //gist.github.com/jdegoes/97459c0045f373f4eaf126998d8f65dc#polymorphic-functions

What's wrong with passing type to your function? 将类型传递给函数有什么问题? Solution : 解决方案

object HighOrderFunction {
    type MyFunction[T] = (Int, T) => List[T]

    def main(args: Array[String]): Unit = {

        val dupInt: MyFunction[Int] = (n, value) => {
            List.fill(n)(value)
        }

        val dupString: MyFunction[String] = (n, value) => {
            List.fill(n)(value)
        }

        val dupDouble: MyFunction[Double] = (n, value) => {
            List.fill(n)(value)
        }

        execute(dupInt, 5, 1)
        execute(dupString, 5, "*")
        execute(dupDouble, 5, 3.14)

    }


    def execute[T](f: MyFunction[T], n: Int, t: T): Unit = {
        println(f(n, t))
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM