我试图将一个haskell示例(我之前遇到过)转换为scalaz。最初的例子就是:
("Answer to the ", (*)) <*> ("Ultimate Question of ", 6) <*> ("Life, the Universe, and Everything", 7)
据我所知,使用this实例。
它没有按字面意思转换为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))
虽然,我已经找了一个实例,但似乎是be there(再次,据我能理解)。
所以,问题是:为什么它不能像这样工作?或者我错过了什么/没有得到正确的?
答案 0 :(得分:5)
Scalaz相当于Control.Applicative
&#39; 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
这里的全部力量 - 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
方法只是将它更好地包装起来。