9

我试图将之前遇到的 haskell 示例转换为 scalaz。原来的例子是这样的:

("Answer to the ", (*)) <*> ("Ultimate Question of ", 6) <*> ("Life, the Universe, and Everything", 7)

据我所知,它使用了这个实例。

它不会从字面上转换为 scalaz:

scala> ("Answer to the ", ((_: Int) * (_: Int)) curried) |@| ("Ultimate Question of ", 6) |@| ("Life, the Universe, and Everything", 7) tupled
res37: (java.lang.String, (Int => (Int => Int), Int, Int)) = (Answer to the Ultimate Question of Life, the Universe, and Everything,(<function1>,6,7))

虽然,我已经寻找了一个实例,它似乎在那里(再次,据我所知)。

所以,问题是:为什么它不能这样工作?或者我错过了什么/没有得到正确的?

4

1 回答 1

5

Scalaz 的Control.Applicative's等价物<*>也称为<*>,尽管它以相反的顺序混淆了它的参数。所以以下工作:

val times = ((_: Int) * (_: Int)) curried
val a = "Answer to the "
val b = "Ultimate Question of "
val c = "Life, the Universe, and Everything"

(c, 7) <*> ((b, 6) <*> (a, times))

或者,正如我在回复您的评论时指出的那样,如果您想坚持使用以下内容,您可以使用以下内容|@|

(a -> times |@| b -> 6 |@| c -> 7)(_ apply _ apply _)

我个人更喜欢这个<*>版本,即使它感觉倒退。


我们可以更详细地了解正在发生的事情。首先,您不需要这里的全部功能Applicative——<code>Apply 就可以了。我们可以Apply使用以下方法获取元组的实例implicitly

scala> val ai = implicitly[Apply[({type λ[α]=(String, α)})#λ]]
ai: scalaz.Apply[[α](java.lang.String, α)] = scalaz.Applys$$anon$2@3863f03a

现在我们可以将我们的第一个元组应用于第二个:

scala> :t ai(a -> times, b -> 6)
(java.lang.String, Int => Int)

结果到第三个:

scala> :t ai(ai(a -> times, b -> 6), c -> 7)
(java.lang.String, Int)

这就是我们想要的:

scala> ai(ai(a -> times, b -> 6), c -> 7)._1
res0: java.lang.String = Answer to the Ultimate Question of Life, the Universe, and Everything

scala> ai(ai(a -> times, b -> 6), c -> 7)._2
res1: Int = 42

上的<*>方法MA只是把它包装得更好一点。

于 2012-06-07T19:44:57.377 回答