0

This is a follow-up to my previous question:

Suppose I want to use Applicative to apply function A => B => C to List[A] and List[B].
I believe it looks like that in Haskell:

pure f <*> as <*> bs // apply f to List[A] and List[B]

or

f <$> as <*> bs 

Does cats provide such a syntax? How would you write it with cats ?

Michael
  • 41,026
  • 70
  • 193
  • 341
  • 1
    `pure f <*> x <*> y` is just the same as `f <$> x <*> y`, where `(<$>)` is a synonym for `fmap`. I don't know Scala's syntax, or anything about `cats`, but from your linked question you seem to know where to find `fmap` and `(<*>)` already, so you should be able to just use them. If an infix synonym for `fmap` doesn't already exist I imagine you can define one, if you want the Scala syntax to look more like the target Haskell expression. – amalloy Aug 01 '17 at 08:12
  • Alternatively, `f <$> x <*> y` is also the same as `liftA2 f x y`. From http://eed3si9n.com/herding-cats/Apply.html, it looks to me like `cats` defines this function and calls it `map2`. – amalloy Aug 01 '17 at 08:48

1 Answers1

2

Some definitions first

import cats._, implicits._
val as = List(1, 2)
val bs = List("a", "b")

Curried funciton

If you have curried function, e.g.

val f = (i: Int) => (s: String) => Vector.fill(i)(s).mkString("")

Then pure f <*> as <*> bs expression is directly translated to cats as

f.pure[List].ap(as).ap(bs)

And f <$> as <*> bs becomes

as.map(f).ap(bs)

Yes, the order is not as natural anymore.


Uncurried function

In Scala very often you will deal with the functions taking multiple parameters:

val f2 = (i: Int, s: String) => Vector.fill(i)(s).mkString("")
// or val f2 = Function.uncurried(f)

For these, cats provides CartesianBuilder syntax:

(as |@| bs).map(f2)

Or, in the newer versions, tuple syntax with map# method (that is subject to be renamed, IIRC)

(as, bs).map2(f2)

All these snippets evaluate to List("a", "b", "aa", "bb")

Oleg Pyzhcov
  • 7,323
  • 1
  • 18
  • 30