【问题标题】:Scala understanding signaturesScala 理解签名
【发布时间】:2016-01-20 23:53:16
【问题描述】:

在 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

^ 这是一个柯里化函数,它接收一个返回 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]

^ 所以“必须”接受一个返回匹配器的函数。但是“which”传入了一个 OptionLikeCheckedMatcher。 "m: => Matcher[T]" 是一个接受 "m" 并返回 "Matcher[T]" 的函数。这与 OptionLikeCheckedMatcher 类型的对象有何相同之处?

有人可以提供关于如何阅读 Scala 类型签名的权威指南吗?

【问题讨论】:

  • 您的问题太长,无法给出完整的答案,但是,我可以告诉您的一件事是“不要太相信 IDE”,尤其是在您编写 Scala 时。对于beSome,有两个声明,一个参数没有参数。 etorreborre.github.io/specs2/api/SPECS2-2.3.12/…
  • 所以 _ == "text/html" 是一个带有通用参数 "" 的函数。这个函数被传递给“which”,它是 SomeMatcher[T] 内部的一个字段,调用无参数“beSome”函数后的返回类型。 which 函数在 {} 中接受这个匿名函数并返回一个 OptionLikeCheckedMatcher[Option, String, String] 或 OptionLikeCheckedMatcher[F, Nothing, String] (我真的不知道),但是匿名中的“”函数是一个字符串。

标签: scala playframework playframework-2.0


【解决方案1】:

我认为您对函数值参数和按名称调用参数之间的区别感到有些困惑。它们相似但不完全相同。在您发布的第一个示例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) => Rwhich 的返回值将是一个 OptionCheckedMatcher。假设这是 Matcher 的子类型(这似乎很合理),这是传递给 must 的值。

【讨论】:

  • 哦,我明白了。 “whenTrue: => Type”表示“whenTrue: (=> Type)”而不是“whenTrue: (_ => Type)”。
  • 通用参数 R 的类型为“AsResult”。在这种情况下,为什么他们将通用参数称为“R”而不是“T”? “U”和“F”是Scala中类的实际名称吗?我以前见过抽象类型,但只在类体内,从来没有在类型签名中。
  • 我怀疑他的意思是“接受 U 作为参数并返回 R”。
  • 这里的“U”是“String”,“R”是“Boolean”
  • 哎呀,是的,很明显@emote_control。不,U 和 F 不是任何类的名称(据我所知 - 请不要写任何 ;)) - 我猜它们只是在一段时间后用完了泛型参数变量?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-09-03
  • 2013-03-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-03-14
相关资源
最近更新 更多