Suppose I have a list of numbers and list of functions:
val xs: List[Int] = List(1, 2, 3)
val fs: List[Int => Int] = List(f1, f2, f3)
Now I would like to use an Applicative
to apply f1
to 1
, f2
to 2
, etc.
val ys: List[Int] = xs <*> fs // expect List(f1(1), f2(2), f3(3))
How can I do it with Scalaz
?
Learning Scalaz spends a few paragraphs on this topic in their introduction to Applicatives. They quote LYAHFGG:
But then adds:
The "not easily" part uses
streamZipApplicative
like in @n1r3's answer:The "not easily" is the part that bothers me. I'd like to borrow from @Travis Brown fantastic answer. He is comparing the use of monads and applicatives (i.e. why use applicatives when you have a monad?):
So, I would say that until a framework provides an applicative that works like your first use-case:
To use
zip
andmap
here instead:To me, this code is much clearer and simpler than the alternatives in scalaz. This is the least powerful abstraction that gets the job done.
pure
for zip lists repeats the value forever, so it's not possible to define a zippy applicative instance for Scala'sList
(or for anything like lists). Scalaz does provide aZip
tag forStream
and the appropriate zippy applicative instance, but as far as I know it's still pretty broken. For example, this won't work (but should):You can use the applicative instance directly (as in the other answer), but it's nice to have the syntax, and it's not too hard to write a "real" (i.e. not tagged) wrapper. Here's the workaround I've used, for example:
And then:
For what it's worth, it looks like this has been broken for at least a couple of years.
I see a solution with
streamZipApplicative
: