6

我目前有点累,所以我可能会错过明显的东西。

我有一个var _minVal: Option[Double],它应保存 s 集合中包含的最小值Double(如果集合为空,则为 None)

在向集合中添加新项目时,我也必须检查是否_minVal为 None 或大于新项目(=新最小值的候选)。

我已经从

_minVal = Some(_minVal match {
    case Some(oldMin) => if (candidate < oldMin) candidate
                         else                    oldMin
    case None         =>                         candidate
})

(不是很干)到

_minVal = Some(min(_minVal getOrElse candidate, candidate))

但仍然认为我可能遗漏了一些东西……</p>

4

2 回答 2

10

如果没有 Scalaz,您将需要支付一些 RY。但我会把它写成:

_minVal = _minVal map (candidate min) orElse Some(candidate)

编辑

Specs / Specs2的名气Eric Torreborre非常友善地追求了我一直没有找到的Scalaz解决方案。作为一个测试框架的人,他以测试格式写了答案,而不是强制性的、有副作用的原版。:-)

这是使用_minValDouble而不是Int,副作用的版本,以及我的一些曲折,因为 Eric 已经完成了艰苦的工作。

// From the question (candidate provided for testing purposes)
var _minVal: Option[Double] = None
def candidate = scala.util.Random.nextDouble

// A function "min"
def min = (_: Double) min (_: Double)

// A function "orElse"
def orElse = (_: Option[Double]) orElse (_: Option[Double])

// Extract function to decrease noise
def updateMin = _minVal map min.curried(_: Double)

// This is the Scalaz vesion for the above -- type inference is not kind to it
// def updateMin = (_minVal map min.curried).sequence[({type lambda[a] = (Double => a)})#lambda, Double]

// Say the magic words
import scalaz._
import Scalaz._   

def orElseSome = (Option(_: Double)) andThen orElse.flip.curried
def updateMinOrSome = updateMin <*> orElseSome

// TAH-DAH!
 _minVal = updateMinOrSome(candidate)
于 2011-08-12T21:11:23.547 回答
7

这是使用 Scalaz 对 Daniel 答案的更新:

这是一个咖喱'min'函数:

def min = (i: Int) => (j: Int) => if (i < j) i else j 

和2个变量:

// the last minimum value
def lastMin: Option[Int] = None

// the new value
def current = 1

现在让我们定义 2 个新函数

// this one does the minimum update
def updateMin = (i: Int) => lastMin map (min(i))

// this one provides a default value if the option o2 is not defined
def orElse = (o1: Int) => (o2: Option[Int]) => o2 orElse Some(o1)

然后使用@dibblego 对为什么 Function1[T, _] 是应用函子的出色解释,我们可以避免“当前”变量的重复:

(updateMin <*> orElse).apply(current) === Some(current)
于 2011-08-22T01:07:53.280 回答