了解Scala中高阶函数中的类型

时间:2014-08-29 05:49:02

标签: scala types higher-order-functions

我自学Scala(来自多年的Java),我遇到了以下代码,我无法完全理解:

case class Email(subject: String, text: String, sender: String, recipient: String)

type EmailFilter = Email => Boolean
def newMailsForUser(mails: Seq[Email], f: EmailFilter) = mails.filter(f)

val sentByOneOf: Set[String] => EmailFilter =
  senders => email => senders.contains(email.sender)

val notSentByAnyOf: Set[String] => EmailFilter =
  senders => email => !senders.contains(email.sender)

val minimumSize: Int => EmailFilter = n => email => email.text.size >= n
val maximumSize: Int => EmailFilter = n => email => email.text.size <= n

我觉得难以理解的部分是缺少类型定义的val:

val sentByOneOf: Set[String] => EmailFilter =
  senders => email => senders.contains(email.sender)

我使用def创建了相同的函数,我可以理解:

def sentByOne(senders: Set[String], email: Email): (Set[String] => EmailFilter) = {
  senders => email => senders.contains(email.sender)
}

该版本的类型来自哪里?另外,后一版本更受欢迎吗?

1 个答案:

答案 0 :(得分:4)

简短的回答,在这个定义中:

val sentByOneOf: Set[String] => EmailFilter =  
  senders => email => senders.contains(email.sender)

扩展为:

val sentByOneOf: Set[String] => Email => Boolean = 
  senders => email => senders.contains(email.sender)

类型在:后定义为Set[String] => EmailFilter。因此传递给sentByOneOf的第一个值是Set[String],第二个值是EmailFilter类型,它是Email => Boolean的别名。

更长的版本:

作为Scala中的所有变量/值,可以在冒号后指定类型,就像在此示例中一样,或者可以从它所引用的表达式中输入。所以在这里:

val sentByOneOf = (senders: Set[String]) => (email: Email) => 
  senders.contains(email.sender)

sentByOneOf的{​​{1}}类型也会被sentByOneOf: Set[String] => (Email => Boolean)所感染,其中Email => Boolean的别名定义为EmailFilter

在scala function values中,这实际上就是你所拥有的,实际上是FunctioN类的实例,其中N是变量的数量。所以你的函数sentByOneOf实际上是这样的:

val sentByOneOf = new Function2[Set[String], Email, Boolean] { 
  def apply(senders: Set[String], email: Email, pred: => Boolean): Boolean = senders.contains(email.sender)
}

顺便说一句,你选择了很多系列的文章,但是第一次使用Scala却很困难:)