在Scala(Play Framework)中,即使我阅读here中的所有符号,我也无法理解类型签名。
例如:
/* matches if a == b */
def equalTo[T](t: => T): BeEqualTo
class BeEqualTo(t: => Any)
extends BeTypedEqualTo[Any]
这些类型的签名到底意味着什么呢?
例如,文档中的“a”和“b”究竟是什么?我所看到的只是“t”。是否为一个函数,它接受一个返回泛型类型T的值的函数?
另一个例子......
说我有这条线......
status(home).must(equalTo(OK))
根据IDE,OK是Int类型的模式或符号。 Int是好的吗?你可以修补一个int来给它一个像“must”这样的函数,但是Int如何进入“equalTo”,一个接受函数的函数?
现在一些类型的签名是有道理的。例如......
def status(of: Future[Result])(implicit timeout: Timeout): Int
^这是一个curried函数,它接受一个返回Result类型的东西,并从某个地方(Scala magic)吸入一个类型为Timeout的隐式参数并返回一个Int。 “home”的类型为“Future [Result]”,因此它适合“status”。
但其他的东西......
contentType(home).must(beSome.which(_ == "text/html"))
^我的IDE说beSome是
类型def beSome[T](check: ValueCheck[T]): SomeCheckedMatcher[T]
^所以“beSome”是一个功能。如果是这种情况,那么我怎么能在它上面附加“.which()”,另一个函数,就好像它是一个对象一样?
另一个例子......
def which[R : AsResult](f: (U) => R): OptionLikeCheckedMatcher[F, Nothing, U]
^你怎么读这些类型的签名? “哪个”接受“f:(U)”,或者我们称之为“(U)”类型的变量?为什么围绕“(U)”不必要的括号?如果R是一个字符串,你不能只说“f:U”并使U成为一个字符串吗?
“必须”就是这样......
def must(m: => Matcher[T]): MatchResult[T]
^所以“必须”接受一个返回Matcher的函数。但是“哪个”传递了OptionLikeCheckedMatcher。 “m:=> Matcher [T]”是一个接收“m”并返回“Matcher [T]”的函数。这与OptionLikeCheckedMatcher类型的对象有什么相同?
有人可以提供有关如何阅读Scala类型签名的权威指南吗?
答案 0 :(得分:3)
我认为您对函数值参数和按名称调用参数之间的区别感到困惑。它们相似但不完全相同。在您发布的第一个示例def equalTo[T](t: => T): BeEqualTo
中,:=>符号表示不立即计算参数(如果只使用冒号声明它),但每次在表达式中使用它时。此链接可能会为您澄清一些事项:https://tpolecat.github.io/2014/06/26/call-by-name.html
在你发布的另一个例子中,def which[R: AsResult](f: (U) => R): OptionCheckedLikeMatcher[F, Nothing, U]
接受一个名为f的函数参数,它接受一个U作为其参数并返回T. U周围的括号确实是不必要的,但是如果它们必须是(例如)f是一个带有2个U型参数的函数 - 然后我们将它写成f: (U, U) => R
。 which
的返回值将是OptionCheckedMatcher。假设这是Matcher的子类型(看起来很合理),这是传递给must
的值。