5

我正在尝试使用 scalaz。我尝试在应用程序代码中编写代码。我写了这样的代码:

val max: Option[Int] = (a |@| b) { math.max(_, _) }

我不太喜欢这段代码。我想编写更接近 Haskell 风格的代码,如下所示:

val max: Option[Int] = { math.max(_, _) } <$> a <*> b

这可能吗。为什么scalaz没有以这种方式实现它?

4

2 回答 2

7

Scala 的类型推断比 Haskell 更受限制(标识符重载,JVM 是原因之一)。推论从左到右进行,函数参数的类型可以从先前的上下文中推导出来(如果在定义的地方,需要一个 arg 类型为 A 的函数),但不能从它们在定义。Scalaz 语法使参数类型可用。大多数情况下,反转它会迫使您编写函数参数类型,例如

{math.max(_: Int, _: Int) } <$> a <*> b
于 2012-07-16T10:21:48.937 回答
4

如果您愿意更详细一点,可以将 Haskell 版本直接翻译成 Scala:

import scalaz._, Scalaz._

val a = Option(1)
val b = Option(2)
val f: Int => Int => Int = x => math.max(x, _)

val c = b <*> (a map f)

或者,作为单行:

val c = 2.some <*> 1.some.map(x => math.max(x, _: Int))

或者:

val c = 2.some <*> (1.some map (math.max _).curried)

顺序是颠倒的,因为这些是方法调用而不是中缀运算符,但它本质上与 相同max <$> a <*> b:我们将函数映射到第一项,然后将结果应用于第二项。

于 2012-07-16T10:58:44.577 回答