是否有类似Haskell的“可能”功能内置于Scala中?

时间:2009-08-07 10:19:05

标签: scala functional-programming

我正在寻找的是这个功能:

def maybe[A, B](a: Option[A])(f: A => B)(g: () => B): B = a match 
{
    case Some(x) => f(x)
    case None => g()
}

这是在Haskell的前奏中所以我认为它可能在某个地方的Scala标准库中,我只是错过了它。我讨厌不得不在项目中重新编码,所以我想知道是否有人知道它在哪里,或者它是否肯定不存在。或者有更好的方法来获得此功能吗?

7 个答案:

答案 0 :(得分:16)

其他答案给出了map + getOrElse组成。只是为了记录,您可以通过以下方式向maybe“添加”Option功能:

implicit def optionWithMaybe[A](opt: Option[A]) = new {
  def maybe[B](f: A=>B)(g: =>B) = opt map f getOrElse g
}

值得注意的是,当函数参数最后出现时,Scala中高阶函数的语法通常更好。因此,组织maybe的更好方法如下:

def maybe[B](g: =>B)(f: A=>B) = opt map f getOrElse g

这可以使用如下:

val opt: Option[String] = ...
opt.maybe("") { _.toUpperCase }

答案 1 :(得分:14)

你可以做到

val opt:Option[A] = // ...
val result:B = opt.map(f).getOrElse(g());

getOrElse采用名字参数,因此只有gopt才会评估None

答案 2 :(得分:4)

如果要遵守惯例,该方法将被称为折叠(参见Either.fold,这是Either的变形)。

答案 3 :(得分:4)

您可以使用scalaz,然后隐式转换为OptionW fold,或者您可以使用Scala 2.10.0-M3并使用内置Option.fold

scala> Some(1).fold(5)(_ * 2)
res5: Int = 2

scala> (None: Option[Int]).fold(5)(_ * 2)
res7: Int = 5

请注意,scalaz折叠签名为fold[X](some: A => X, none: => X),而内置似乎为fold[X](none: => X)(some: A => X)

答案 4 :(得分:0)

我认为没有。我能想到的最好的方法是将Option的“map”和“getOrElse”链接在一起:

scala> var a: Option[String] = Some("hello")
a: Option[String] = Some(hello)

scala> a.map(_.toUpperCase).getOrElse("empty") 
res19: java.lang.String = HELLO

scala> a = None
a: Option[String] = None

scala> a.map(_.toUpperCase).getOrElse("empty")
res21: java.lang.String = empty

答案 5 :(得分:0)

我认为没有。但是,我会将其写为g名称:

def maybe[A, B](a: Option[A])(f: A => B)(g: => B): B = a.map(f).getOrElse(g)

这更像Scala-和Haskell,使用起来更好。

答案 6 :(得分:0)

我会使用Option.fold

opt.fold(g)(f)

请注意g是名字,就像getOrElse一样。还要注意案件的倒置。