在 Scala(Play Framework)中,即使我读完了 here 中的所有符号,我也无法理解类型签名。 。
例如:
/* matches if a == b */
def equalTo[T](t: => T): BeEqualTo
class BeEqualTo(t: => Any)
extends BeTypedEqualTo[Any]
这些类型签名到底意味着什么?
例如,文档中的“a”和“b”到底是什么?我只看到“t”。 equalTo 是一个接受返回泛型类型 T 值的函数的函数吗?
另一个例子...
假设我有这条线...
status(home).must(equalTo(OK))
根据 IDE,OK 是 Int 类型的模式或符号。那么 Int 也可以吗?你可以给一个 int 打猴子补丁,给它一个像“must”这样的函数,但是 Int 如何进入“equalTo”这个接受函数的函数内部呢?
现在一些类型签名有意义了。例如...
def status(of: Future[Result])(implicit timeout: Timeout): Int
^ 这是一个柯里化(Currying)函数,它接受一个 future,返回 Result 类型的东西,并从某个地方(Scala 魔法)吸收 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]
^ 你到底如何阅读这些类型签名? “which”接受“f:(U)”,或者我们称之为“(U)”类型的“f”的变量?为什么“(U)”两边有不必要的括号?如果 R 是字符串,你不能只说“f: U”并使 U 成为字符串吗?
“必须”是这样的...
def must(m: => Matcher[T]): MatchResult[T]
^ 所以“必须”接受一个返回 Matcher 的函数。但“which”正在传递一个 OptionLikeCheckedMatcher。 “m: => Matcher[T]”是一个接受“m”并返回“Matcher[T]”的函数。它与 OptionLikeCheckedMatcher 类型的对象有何相同?
有人可以提供关于如何阅读 Scala 类型签名的明确指南吗?
最佳答案
我认为您对函数值参数和按名称调用参数之间的区别感到有点困惑。它们相似但不完全相同。在您发布的第一个示例中,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
的值。
关于Scala 理解签名,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34891921/