5

I am experimenting with scalaz. I tried writing code in applicative code. I wrote code like this:

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

I didn't like this code very much. I would like to code which is closer to Haskell style, something like this:

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

Is this possible. And why scalaz didn't implement it this way?

Konstantin Solomatov
  • 10,252
  • 8
  • 58
  • 88
  • Just out of curiosity: What is it that you dislike? I find the "scalaz version" cleaner to the (my) eye... – Jan Jul 16 '12 at 11:03
  • 1
    In Haskell you'd actually just write `max <$> a <*> b`, which I personally much prefer to any of the Scalaz versions. – Travis Brown Jul 16 '12 at 11:09
  • @TravisBrown how would you write it for more then two args? "fun <$> a <*> b <*> c"? – Jan Jul 16 '12 at 11:18
  • @Jan correct. `f <$> x` is the same as `pure f <*> x`; since all Haskell functions are curried, chaining the left-associative <*> in this way Just Works. – Dan Burton Jul 16 '12 at 13:46
  • @DanBurton nice - when I have some time I will spend it with Haskell - someday :-) – Jan Jul 16 '12 at 18:35

2 Answers2

7

Scala's type inference, is much more limited than in Haskell (identifier overloading, which comes with the JVM being one of the reasons). Inferences flows from left to right, and the type of the arguments of a function may be deduced from previous context (if at the place of the definition, a function with arg type A is expected), but not from how they are used in the definition. Scalaz syntax makes the arguments types available. Reversing it would most of the time force you to write the function arguments types, e.g.

{math.max(_: Int, _: Int) } <$> a <*> b
Didier Dupont
  • 29,398
  • 7
  • 71
  • 90
  • There are many times, though, when I am dealing with an existing function value whose full type is already known. In that case, I really wish I had the `f <$> a <*> b` syntax. Since we already have the backwards applicative builder syntax `(a |@| b) { math.max(_, _) }` for the anonymous function case, I don't see why we can't have the natural Haskell-like syntax for the function value case. – Tim Yates Dec 16 '13 at 15:02
4

You can translate the Haskell version directly into Scala, if you're willing to be a little more verbose:

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)

Or, as a one-liner:

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

Or:

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

The order is reversed because these are method calls instead of infix operators, but it's essentially the same thing as max <$> a <*> b: we map the function over the first item, and then apply the result to the second.

Travis Brown
  • 138,631
  • 12
  • 375
  • 680