How can I implement a similar Haskell function in Scala 3 and Cats?
ghci> (+) <$> (+1) <*> (+1) $ 10
22
There was a solution using mapN. It is mentioned here, Using functions as applicative functors/cartesians, but I want a solution using <*> instead of mapN. I tried something similar but it won't compile
import cats._
import cats.implicits._
type Func1[Y] = Int => Y
val add1: Func1[Int] = (x: Int) => x + 1
val addXY: Func1[Func1[Int]] = (x: Int) => (y: Int) => x + y
val foo: Func1[Func1[Func1[Int]]] = Applicative[Func1].pure(addXY)
val bar: Func1[Func1[Int]] = Applicative[Func1].pure(add1)
val foobar = foo <*> bar
foobar(10) // should be 22 but it can't compile
Please advise. Thanks
Scala Cats admits functions as
Applicativeinstances, just like Haskell does. The Haskell code you wrote isWe can write these functions in Scala as
Now
<*>works like it does in Haskell, but<$>doesn't exist as infix (not least of all because$isn't a symbol character in JVM-based languages). Remember thatf <$> xis just equivalent tofmap f x, or (by theApplicativelaws)pure f <*> x.So we can write
Now, while Cats doesn't provide an infix
<$>that I know of, we can easily write one ourselves as an extension method. We can't name it<$>because the dollar sign is funny on the JVM, but we can write<@>instead.Now we can say
Complete example:
Scala 2
All of the above is written in Scala 3. If you're in Scala 2, then you have to do a bit of messy business to get Scala to treat the functions the way you want. As you've already seen, you have to write a
typealias to get the right type-level generic behavior (if you want to callpure, for instance). Thedeffunctions have to be explicitly converted to functions with a suffix_. And theextensionmethod will need to be an old-schoolimplicit class.So all in all, this is the same program written in Scala 2.