6

我试图理解在高阶函数的上下文中按名称类型注释的含义。这是一个例子:

object Test { 
  def apply[A, B](f: (=> A) => B, x: => A): B = f(x) 
  def const[A](ignored: A): Int = 1
  val res: Int = apply(const, ???)
}

const它的论点是严格的(即它缺少=>注释),那么为什么它不强制它的论点(???在这种情况下)并引发异常?

这里有描述语义的论文吗?

我在这里寻找权威的答案。

4

2 回答 2

5

函数f中的参数apply是 a Funcion1,它接受一个按名称调用的类型参数A并返回 a B。因此,f(x)不会评估 call-by-name 参数x,而是将其引用直接传递给f.

res理解如下是有帮助的:

def res[C]: Int = apply[C, Int](const, ???)

在您的示例C中将是一个非特定类型。现在const在这一行中推断出的类型参数是什么?它是=> C。不幸的是,您不能输入该参数:

def res[C]: Int = apply[C, Int](const[=> C], ???)  // illegal syntax

但是您可以验证发生了什么:

def res[C]: Int = apply[C, Int](const[Nothing], ???)

给你

<console>:10: error: type mismatch;
 found   : Nothing => Int
 required: => C => Int
         def res[C]: Int = apply[C, Int](const[Nothing], ???)
                                              ^

这种类型在内部显示const为 a Function0[Int](因此 Scala 隐含地将按名称调用或“thunk”参数视为没有参数的函数)。您可以再次验证这一点:

def const[A](ignored: A): Int = if (ignored.isInstanceOf[Function0[_]]) 1 else 0

现在Test.res会给你1(意思ignored是确实是一个Function0)。


因此,以不同的方式回答这个问题,const有一个急切的 type 参数A,但这并不重要,因为A在您的示例中成为一个函数,并且您从不应用该函数,因此???永远不会执行。


关于为什么 Scala 中同时存在“thunk”或无括号函数和空括号函数 ( )存在一些争论Function0

于 2013-04-18T23:29:28.133 回答
0

我正在打开另一个答案,因为您似乎仍然不清楚发生了什么:

通常,严格属性是根据所应用的函数(在本例中为 const)定义的,但您的解释主要是关于实现以及如何构造 const 的参数。

我将用不同的类型名称重述您的对象:

object Test { 
  def apply[A, B](f: (=> A) => B, x: => A): B = f(x) 
  def const[C](ignored: C): Int = 1
  def res[A1]: Int = apply[A1, Int](const, ???)
}

现在,让我们用 , 交换名称参数Function0,以突出显示“惰性”隐藏的位置:

object Test { 
  def apply[A, B](f: (() => A) => B, x: () => A): B = f(x) 
  def const[C](ignored: C): Int = 1
  def res[A1]: Int = apply[A1, Int](const[() => A1], () => ???)
}

你看,定义const无关紧要。重要的是xto 的参数apply是按名称(或上一个版本中的函数)。所以使用函数参数调用f(x),所以无论的主体是什么,此时都不会评估。f xx

于 2013-04-19T10:50:29.323 回答