why we need Free monad to interpret Action to Future - scala

I wrote one example to use scalaz.Free to to map Action to Future, it looks pretty cool. However, I am trying to understand the benefits of it. I hope I can get the answer here. Here is my code snippet
Firstly, I create an Action, which is AST.
trait Action[A]
case class GetNumberAction(x: Int) extends Action[Int]
case class GetStringAction(x: String) extends Action[String]
case class ConvertToIntAction(x: String) extends Action[Int]
case class AddAction(x: Int, y: Int) extends Action[Int]
Then, I create a class to map Action to ASTMonad by using Scalaz Free and Coyonda.
type Functor[A] = Coyoneda[Action, A]
type ASTMonad[A]= Free[Functor, A]
def toMonad[A](action: Action[A]): ASTMonad[A] = Free.liftFC[Action, A](action)
object ADTMonad {
def getNumber(x: Int): ASTMonad[Int] = toMonad(GetNumberAction(x))
def getString(x: String): ASTMonad[String] = toMonad(GetStringAction(x))
def converToInt(x: String): ASTMonad[Int] = toMonad(ConvertToIntAction(x))
def add(x: Int, y: Int): ASTMonad[Int] = toMonad(AddAction(x, y))
}
At last, I create an Interpreter to interpret Action to Future
object Interpreter extends (Action ~> Future) {
def apply[A](action: Action[A]): Future[A] = {
action match {
case GetNumberAction(x) => Future(x)
case GetStringAction(x) => Future(x)
case ConvertToIntAction(x) => Future(x.toInt)
case AddAction(x, y) => Future(x + y)
}
}
}
When I run it, I can use
val chain = for {
number <- ASTMonad.getNumber(x)
str <- ASTMonad.getString(y)
convertedNumber <- ASTMonad.converToInt(str)
total <- ASTMonad.add(number, convertedNumber)
} yield total
chain.runWith(Interpreter)
It seems to work and I think I understand this monad and interpreter things. However, I am thinking what is the benefits comparing to the solution if I am using Future.flatmap and map directly ?
for {
number <- Future(x)
str <- Future(y)
convertedNumber <- Future(str.toInt)
total <- Future(number + convertedNumber)
} yield total
The code of using Future flatmap and map looks simpler to me. So back to my questions, do we need to use Free monad to interpret the business logic to Future, since Future has already provided flatMap and map. If it does, can someone give me more concrete example, so I can see the benefits ?
Thanks in advance

A good and motivated example for using free applicative are command-line parsers, let's call the type CLI[A].
A value of type CLI[A] means you will get an A if you provide command-line arguments (Array[String]) and they can be parsed successfully. Now this functionality is isomorphic to Array[String] -> Either[String,A] when using Either for error handling.
Because you made CLI applicative, you can map and apply (combine) values. You can for example create a Int argument count, another Int argument count2, and combine them to a final sum: CLI[Int] that holds their sum.
Suppose you apply the computation directly, this yields something that is "only" equivalent to Array[String] -> Either[String,Int]. But if you want to create a help text you have to know both initial arguments, and this information is lost.
Free to the rescue. With Free you can retain the computation graph, which you can use to extract all initial CLI values that are directly parsed from the arguments. You can then later run the computation which yields the final value of sum by providing the parse results for all initial arguments.
Of course you could implement a special CLI that keeps track of all the initial values over computations, but Free let's you avoid this extra work.

Related

Scala Dynamically built Function Chain with varying inputs

I'm trying to dynamically create a chain of functions to perform on a numeric value. The chain is created at runtime from text instructions.
The trick is that the functions vary in what types they produce. Some functions produce a Double, some produce a Long.
Update
The core issue is that I have a massive amount of data to process, but different values require different processing. In addition to the data I have specifications on how to extract and manipulate values to their final form, such as applying a polynomial, using a lookup table, changing the binary format (like 2s Compliment), etc. These specs are in a file of some sort (I'm creating the file form a database, but that's not important to the conversation), and I can apply these specs to multiple data files.
so with functions (these are just exmaples; there are tons of them):
def Multiply(input: Long, factor:Double):Double = input*factor
def Poly(input:Double, co:Array[Double]):Double = // do some polynomial math
I can manually create a chain like this:
val poly = (x: Double) => EUSteps.Poly(x,Array[Double](1,2))
val mult = (x: Long) => EUSteps.Multiply(x, 1.5)
val chain = mult andThen poly
And if I call chain(1) I get 4
Now I want to be able to parse a string like "MULT(1.5);POLY(1,2)" and get that same chain. The idea is that I can define the chain however I want. Maybe its "MULT(1.5);MULT(2);POLY(1,2,3)." for example. So I can make the functions generic, like this:
def Multiply[A](value: A, factor:Double)(implicit num: Numeric[A]) = num.toDouble(value)*factor
def Poly[A](value:A, co:Array[Double])(implicit num: Numeric[A]) = { // do some poly math
Parsing the string isn't hard as it's very simple.
How can I build the chain dynamically?
If it helps, the input is always going to be Long for the first step in the chain. The result could be Long or Double, and I'm OK with it if I have to do two versions based on the end result, so one that goes Long to Long, the other that goes Long to Double.
What I've tried
If I define my functions as having the same signature, like this:
def Multiply(value: Double, factor:Double) = value*factor
def Poly(value:Double, co:Array[Double]) = {
I can do it as part of a map operation:
def ParseList(instruction:String) = {
var instructions = instruction.split(';')
instructions.map(inst => {
val instParts = inst.split(Array(',','(',')'))
val instruction = instParts(0).toUpperCase()
val instArgs = instParts.drop(1).map(arg => arg.toDouble)
instruction match {
case "POLY" => (x: Double) => EUSteps.Poly(x,instArgs)
case "MULTI" => (x: Double) => Multiply(x,instArgs(0))
}
}).reduceLeft((a,b) => a andThen b)
However, that breaks as soon as I change one of the arguments or return types to Long:
def Multiply(value: Long, factor:Double) = value*factor
And change my case
instruction match {
case "POLY" => (x: Double) => EUSteps.Poly(x,instArgs)
case "MULTI" => (x: Long) => Multiply(x,instArgs(0))
}
}).reduceLeft((a,b) => a andThen b)
Now the Reduce is complaining because it wanted Double => Double instead of Long => Double
Update 2
The way I solved it was to do what Levi suggested in the comments. I'm sure this is not very Scala-y, but when in doubt I go back to my OO roots. I suspect there is a more elegant way to do it though.
I declared an abstract class called ParamVal:
abstract class ParamVal {
def toDouble(): Double
def toLong(): Long
}
Then Long and Double types to go with it that implement the conversions:
case class DoubleVal(value: Double) extends ParamVal {
override def toDouble(): Double = value
override def toLong(): Long = value.toLong
}
case class LongVal(value: Long) extends ParamVal {
override def toDouble(): Double = value.toDouble
override def toLong(): Long = value
}
This lets me define all function inputs as ParamVal, and since each one expects a certain input type it's easy to just call toDouble or toLong as needed.
NOTE: The app that creates these instructions already makes sure the chain is correct.
Some ideas:
Analyze the string chain upfront and figure out what will be the type of the final result and then use it for all steps all along. You will need a family of functions for each type.
Try to use Either[Long, Double] in the reduce part.

What's the purpose of Currying given other alternatives to return a function in Scala?

I'm currently doing a Scala course and recently I was introduced to different techniques of returning functions.
For example, given this function and method:
val simpleAddFunction = (x: Int, y: Int) => x + y
def simpleAddMethod(x: Int, y: Int) = x + y
I can return another function just doing this:
val add7_v1 = (x: Int) => simpleAddFunction(x, 7)
val add7_v2 = simpleAddFunction(_: Int, 7)
val add7_v3 = (x: Int) => simpleAddMethod(x, 7)
val add7_v4 = simpleAddMethod(_: Int, 7)
All the values add7_x accomplish the same thing, so, whats the purpose of Currying then?
Why I have to write def simpleCurryMethod(x: Int)(y: Int) = x + y if all of the above functions do a similar functionality?
That's it! I'm a newbie in functional programming and I don't know many use cases of Currying apart from saving time by reducing the use of parameters repeatedly. So, if someone could explain me the advantages of currying over the previous examples or in Currying in general I would be very grateful.
That's it, have a nice day!
In Scala 2 there are only four pragmatic reasons for currying METHODS (as far as I can recall, if someone has another valid use case then please let me know).
(and probably the principal reason to use it) to drive type inference.
For example, when you want to accept a function or another kind of generic value whose generic type should be inferred from some plain data. For example:
def applyTwice[A](a: A)(f: A => A): A = f(f(a))
applyTwice(10)(_ + 1) // Here the compiler is able to infer that f is Int => Int
In the above example, if I wouldn't have curried the function then I would need to have done something like: applyTwice(10, (x: Int) => x + 1) to call the function.
Which is redundant and looks worse (IMHO).
Note: In Scala 3 type inference is improved thus this reason is not longer valid there.
(and probably the main reason now in Scala 3) for the UX of callers.
For example, if you expect an argument to be a function or a block it is usually better as a single argument in its own (and last) parameter list so it looks nice in usage. For example:
def iterN(n: Int)(body: => Unit): Unit =
if (n > 0) {
body
iterN(n - 1)(body)
}
iterN(3) {
println("Hello")
// more code
println("World")
}
Again, if I wouldn't have curried the previous method the usage would have been like this:
iterN(3, {
println("Hello")
// more code
println("World")
})
Which doesn't look that nice :)
(in my experience weird but valid) when you know that majority of users will call it partially to return a function.
Because val baz = foo(bar) _ looks better than val baz = foo(bar, _) and with the first one, you sometimes don't the the underscore like: data.map(foo(bar))
Note: Disclaimer, I personally think that if this is the case, is better to just return a function right away instead of currying.
Edit
Thanks to #jwvh for pointing out this fourth use case.
(useful when using path-dependant types) when you need to refer to previous parameters. For example:
trait Foo {
type I
def bar(i: I): Baz
}
def run(foo: Foo)(i: foo.I): Baz =
foo.bar(i)

Fibonacci memoization in Scala with Memo.mutableHashMapMemo

I am trying implement the fibonacci function in Scala with memoization
One example given here uses a case statement:
Is there a generic way to memoize in Scala?
import scalaz.Memo
lazy val fib: Int => BigInt = Memo.mutableHashMapMemo {
case 0 => 0
case 1 => 1
case n => fib(n-2) + fib(n-1)
}
It seems the variable n is implicitly defined as the first argument, but I get a compilation error if I replace n with _
Also what advantage does the lazy keyword have here, as the function seems to work equally well with and without this keyword.
However I wanted to generalize this to a more generic function definition with appropriate typing
import scalaz.Memo
def fibonachi(n: Int) : Int = Memo.mutableHashMapMemo[Int, Int] {
var value : Int = 0
if( n <= 1 ) { value = n; }
else { value = fibonachi(n-1) + fibonachi(n-2) }
return value
}
but I get the following compilation error
cmd10.sc:4: type mismatch;
found : Int => Int
required: Int
def fibonachi(n: Int) : Int = Memo.mutableHashMapMemo[Int, Int] {
^Compilation Failed
Compilation Failed
So I am trying to understand the generic way of adding adding a memoization annotation to a scala def function
One way to achieve a Fibonacci sequence is via a recursive Stream.
val fib: Stream[BigInt] = 0 #:: fib.scan(1:BigInt)(_+_)
An interesting aspect of streams is that, if something holds on to the head of the stream, the calculation results are auto-memoized. So, in this case, because the identifier fib is a val and not a def, the value of fib(n) is calculated only once and simply retrieved thereafter.
However, indexing a Stream is still a linear operation. If you want to memoize that away you could create a simple memo-wrapper.
def memo[A,R](f: A=>R): A=>R =
new collection.mutable.WeakHashMap[A,R] {
override def apply(a: A) = getOrElseUpdate(a,f(a))
}
val fib: Stream[BigInt] = 0 #:: fib.scan(1:BigInt)(_+_)
val mfib = memo(fib)
mfib(99) //res0: BigInt = 218922995834555169026
The more general question I am trying to ask is how to take a pre-existing def function and add a mutable/immutable memoization annotation/wrapper to it inline.
Unfortunately there is no way to do this in Scala unless you are willing to use a macro annotation for this which feels like an overkill to me or to use some very ugly design.
The contradicting requirements are "def" and "inline". The fundamental reason for this is that whatever you do inline with the def can't create any new place to store the memoized values (unless you use a macro that can re-write code introducing new val/vars). You may try to work this around using some global cache but this IMHO falls under the "ugly design" branch.
The design of ScalaZ Memo is used to create a val of the type Function[K,V] which is often written in Scala as just K => V instead of def. In this way the produced val can contain also the storage for the cached values. On the other hand syntactically the difference between usage of a def method and of a K => V function is minimal so this works pretty well. Since the Scala compiler knows how to convert def method into a function, you can wrap a def with Memo but you can't get a def out of it. If for some reason you need def anyway, you'll need another wrapper def.
import scalaz.Memo
object Fib {
def fib(n: Int): BigInt = n match {
case 0 => BigInt(0)
case 1 => BigInt(1)
case _ => fib(n - 2) + fib(n - 1)
}
// "fib _" converts a method into a function. Sometimes "_" might be omitted
// and compiler can imply it but sometimes the compiler needs this explicit hint
lazy val fib_mem_val: Int => BigInt = Memo.mutableHashMapMemo(fib _)
def fib_mem_def(n: Int): BigInt = fib_mem_val(n)
}
println(Fib.fib(5))
println(Fib.fib_mem_val(5))
println(Fib.fib_mem_def(5))
Note how there is no difference in syntax of calling fib, fib_mem_val and fib_mem_def although fib_mem_val is a value. You may also try this example online
Note: beware that some ScalaZ Memo implementations are not thread-safe.
As for the lazy part, the benefit is typical for any lazy val: the actual value with the underlying storage will not be created until the first usage. If the method will be used anyway, I see no benefits in declaring it as lazy

Making multiple API calls in a functional way

What would it be the best approach to solve this problem in the most functional (algebraic) way by using Scala and Cats (or maybe another library focused on Category Theory and/or functional programming)?
Resources
Provided we have the following methods which perform REST API calls to retrieve single pieces of information?
type FutureApiCallResult[A] = Future[Either[String, Option[A]]]
def getNameApiCall(id: Int): FutureApiCallResult[String]
def getAgeApiCall(id: Int): FutureApiCallResult[Int]
def getEmailApiCall(id: Int): FutureApiCallResult[String]
As you can see they produce asynchronous results. The Either monad is used to return possible errors during API calls and Option is used to return None whenever the resource is not found by the API (this case is not an error but a possible and desired result type).
Method to implement in a functional way
case class Person(name: String, age: Int, email: String)
def getPerson(id: Int): Future[Option[Person]] = ???
This method should used the three API calls methods defined above to asynchronously compose and return a Person or None if either any of the API calls failed or any of the API calls return None (the whole Person entity cannot be composed)
Requirements
For performance reasons all the API calls must be done in a parallel way
My guess
I think the best option would be to use the Cats Semigroupal Validated but I get lost when trying to deal with Future and so many nested Monads :S
Can anyone tell me how would you implement this (even if changing method signature or main concept) or point me to the right resources? Im quite new to Cats and Algebra in coding but I would like to learn how to handle this kind of situations so that I can use it at work.
The key requirement here is that it has to be done in parallel. It means that the obvious solution using a monad is out, because monadic bind is blocking (it needs the result in case it has to branch on it). So the best option is to use applicative.
I'm not a Scala programmer, so I can't show you the code, but the idea is that an applicative functor can lift functions of multiple arguments (a regular functor lifts functions of single argument using map). Here, you would use something like map3 to lift the three-argument constructor of Person to work on three FutureResults. A search for "applicative future in Scala" returns a few hits. There are also applicative instances for Either and Option and, unlike monads, applicatives can be composed together easily. Hope this helps.
You can make use of the cats.Parallel type class. This enables some really neat combinators with EitherT which when run in parallel will accumulate errors. So the easiest and most concise solution would be this:
type FutureResult[A] = EitherT[Future, NonEmptyList[String], Option[A]]
def getPerson(id: Int): FutureResult[Person] =
(getNameApiCall(id), getAgeApiCall(id), getEmailApiCall(id))
.parMapN((name, age, email) => (name, age, email).mapN(Person))
For more information on Parallel visit the cats documentation.
Edit: Here's another way without the inner Option:
type FutureResult[A] = EitherT[Future, NonEmptyList[String], A]
def getPerson(id: Int): FutureResult[Person] =
(getNameApiCall(id), getAgeApiCall(id), getEmailApiCall(id))
.parMapN(Person)
this is the only solution i came across with but still not satisfied because i have the feeling it could be done in a cleaner way
import cats.data.NonEmptyList
import cats.implicits._
import scala.concurrent.Future
case class Person(name: String, age: Int, email: String)
type FutureResult[A] = Future[Either[NonEmptyList[String], Option[A]]]
def getNameApiCall(id: Int): FutureResult[String] = ???
def getAgeApiCall(id: Int): FutureResult[Int] = ???
def getEmailApiCall(id: Int): FutureResult[String] = ???
def getPerson(id: Int): FutureResult[Person] =
(
getNameApiCall(id).map(_.toValidated),
getAgeApiCall(id).map(_.toValidated),
getEmailApiCall(id).map(_.toValidated)
).tupled // combine three futures
.map {
case (nameV, ageV, emailV) =>
(nameV, ageV, emailV).tupled // combine three Validated
.map(_.tupled) // combine three Options
.map(_.map { case (name, age, email) => Person(name, age, email) }) // wrap final result
}.map(_.toEither)
Personally I prefer to collapse all non-success conditions into the Future's failure. That really simplifies the error handling, like:
val futurePerson = for {
name <- getNameApiCall(id)
age <- getAgeApiCall(id)
email <- getEmailApiCall(id)
} yield Person(name, age, email)
futurePerson.recover {
case e: SomeKindOfError => ???
case e: AnotherKindOfError => ???
}
Note that this won't run the requests in parallel, to do so you'd need to move the future's creation outside of the for comprehension, like:
val futureName = getNameApiCall(id)
val futureAge = getAgeApiCall(id)
val futureEmail = getEmailApiCall(id)
val futurePerson = for {
name <- futureName
age <- futureAge
email <- futureEmail
} yield Person(name, age, email)

Is this scala function to heavy/doing too many things to unit test properly?

OK, so I am looking at testing libraries, in particular ScalaTest & ScalaMock.
I wanted to write a test to test this function that I have written:
def gameMenuSelect(): State = {
Try(UI.readOption) match {
case Success(i) => {
i match {
case 1 => HumanGame
case 2 => MachineGame
case 3 => sys.exit(0)
case _ =>
UI.invalidSelectionMsg
ChoosingGame
}
}
case Failure(e) => UI.invalidSelectionMsg; ChoosingGame
}
}
A bit of background, UI.readOption is a simple scala.io.StdIn.readInt.
State is a Trait - subsequently HumanGame, MachineGame and ChoosingGame are also Traits that extend State.
The problem is I have no idea how I would test it, the reason is because I feel like this function does too much.
It is reading input, validating that the input given is indeed a number/integer and not throwing a NumberFormatException. Given that the input is an integer it is match on allowable integers.
I really feel like there is a lot to test, also a lot that I am not sure is unit testable.
Could I have some opinions on whether you feel that this function is doing too many things, whether I should try to break up the reading of the integer and the matching of it?
Thanks.
Yes, should absolutely try to separate the "side-effecting" bits, reading and writing, from the selection logic. The selection logic can return something like
import scalaz._, Scalaz._
def selectGame(i: Int): GameError \/ State =
i match {
case 1 => HumanGame.right
case 2 => MachineGame.right
case _ => InvalidGame(i).left
}
sealed trait GameError
case class InvalidGame(i: Int) extends GameError
object GameError {
def render(e: GameError): String =
e match {
case InvalidGame(i) =>
s"Invalid game choice: $i. Only 1 and 2 are acceptable values"
}
}
Note that I also model the error into a specific type instead of just using strings.
Then you can do the same with your number parsing:
def parseInt(i: String): ParseError \/ Int =
???
For your "effects" you can use Scalaz IO for the interactions with the console:
def readLine: IO[String] =
IO(StdIn.readLine)
def printLine(line: String): IO[Unit] =
IO(println(line))
Then, with a bit more code, you can use the EitherT[IO, E, A] monad to "assemble" all your functions:
// I will provide a full example if you want to go this way
val actions: EitherT[IO, ApplicationError, Unit] =
for {
line <- readLine
i <- parseInt(line)
s <- selectGame(i)
_ <- printLine(s.render)
} yield ()
The actions value will both have IO side-effects and collect errors, stopping the process if there are any.
Eventually this all makes your testing a lot easier because you have isolated the "pure" parts which are way easier to test: no setup, no mocks, just pure functions.
In my opinion, there are too many side effects in your function. Not only the reading of the integer, but also sys.exit(0). You could change the method to accept the integer as a parameter, and also add an EndingGame state that you could use for case 3. You would then have a pure function that is easily testable.