关于scala:(scalaz)可以选择调用链式方法

(scalaz) to optionally invoke a chained method

我有:

1
2
3
4
5
6
val having: Option[String] = ...

val averageStream = having match {
  case Some(expr) => stream[TimeMovingAverage].filter("name = '#name'").where(expr)
  case None       => stream[TimeMovingAverage].filter("name = '#name'")
}

是否有一些可消除重复的scala兹魔法?

我可以做类似

的事情

1
2
val averageStream1 = stream[TimeMovingAverage].filter("name = '#name'")
val averageStream2 = having.map(averageStream1.where(_))

但这似乎有点尴尬。我想我正在寻找类似

的东西

1
2
val averageStream = stream[TimeMovingAverage].filter("name = '#name'") |?| having.cata(_.where(_), _)
// Clearly some ambiguities with the _'s here

1
2
3
stream[TimeMovingAverage].filter("name = '#name'") |> { str =>
  having.cata(str.where(_), str)
}

甚至

1
2
3
stream[TimeMovingAverage].filter("name = '#name'") |> (
  having.cata(expr => _.where(expr), identity) : T => T
)

必须将

T => T更改为stream[TimeMovingAverage]的类型,这会使它不太实用,除非您在scalaz中找到了|>的以下特化或自己定义了它:

1
2
3
4
5
6
7
8
implicit def WrapIt[T](t: T) = new {
  def |~> (arg: T => T) = arg(t)
  def |?> (arg: Option[T => T]): T = arg.getOrElse(identity (_:T)).apply(t)
}

stream[TimeMovingAverage].filter("name = '#name'") |~> having.cata(expr => _.where(expr), identity)

stream[TimeMovingAverage].filter("name = '#name'") |?> having.map(expr => _.where(expr))

不确定,但是是否真的应该提出这样的建议。