Scala get value from lambda - scala

I want to get value from function that passed as parameter and returns Option[Int], after that if I have None throw an exception and in any other case return value
I tried to do like this:
def foo[T](f: T => Option[Int]) = {
def helper(x: T) = f(x)
val res = helper _
res match {
case None => throw new Exception()
case Some(z) => z
}
I call it like this:
val test = foo[String](myFunction(_))
test("Some string")
I have compilation error with mismatched types in match section (Some[A] passed - [T] => Option[Int] required)
As I understood res variable is reference to the function and I cannot match it with optional either call get\gerOrElse methods.
Moreover I probably just dont get how the underscore works and doing something really wrong, I'm using it here to pass a something as parameter to function f, can you explain me where I made a mistake?

helper is a method taking a T and returning an Option[Int].
res is a function T => Option[Int].
Difference between method and function in Scala
You can't match a function T => Option[Int] with None or Some(z).
You should have an Option[Int] (for example the function applied to some T) to make such matching.
Probably you would like to have
def foo[T](f: T => Option[Int]) = {
def helper(x: T) = f(x)
val res = helper _
(t: T) => res(t) match {
case None => throw new Exception()
case Some(z) => z
}
}
or just
def foo[T](f: T => Option[Int]): T => Int = {
t => f(t) match {
case None => throw new Exception()
case Some(z) => z
}
}
or
def foo[T](f: T => Option[Int]): T => Int =
t => f(t).getOrElse(throw new Exception())

Related

Recursive Partial application until type/result desired

Is there any way to write a function(lst: List(T), fun: ) that iterates through lst and partially applies each element to fun and returning a new function each time and recursively doing this until the result of the function application is :Future[T] as desired and not a function type?
fun is a curried function
Something like this.
def partialAppRec(lst : List[T], fun: ?) =
//pardon the non-exhaustive pattern match
lst match {
case x::xs =>
val test = fun(x)
if (test: Future[T]) return test
partialAppRec(xs, (fun(x) _) )
}
But what type would fun be? Is there anyway to say that fun: , disregarding parameters that it could take. I want to be able to take in a fun of variable parameters but that returns Future[T]. f : ..=>Future[T] but I'm not sure something like this exists.
Any tips/suggestions? Thanks.
How about Either?
trait Fun[T] extends Function[T, Either[Fun[T], Future[T]]]
object Fun {
def apply[T](f: T => Either[Fun[T], Future[T]]) =
new Fun[T] { def apply(t: T) = f(t) }
}
def partialAppRec[T](lst: List[T], fun: Fun[T]): Future[T] = lst match {
case Nil => ???
case head :: tail => fun(head) match {
case Right(fu) => fu
case Left(f) => partialAppRec(tail, f)
}
}

scala map method can not correctly resolve function type in collection with fixed function types

I have the following code,
def obsKPI[T](kpi: Option[T], f: T => Unit) = {
kpi match {
case Some(obsValue) => f(obsValue)
case _ => Unit
}
}
def func1(str:String):Unit = println(str)
def func2(num: Int):Unit = println(num)
//option1: val inputArgs = List((Some("first"),(func1 _)),(Some("third"), (func1 _)))
//option2: val inputArgs = List((Some(456), (func2 _)),(None,(func2 _)))
// option3:
val inputArgs = List((Some("first"),(func1 _)),(Some(456), (func2 _)),(Some("third"), (func1 _)),(None,(func2 _)))
inputArgs.map(x => obsKPI(x._1, x._2))
when running either option 1 or 2 (the inputArgs list contains function of only String=>Unit or Int=>Unit), the code works, but when running option 3, I get an error:
:68: error: type mismatch;
found : Int with String => Unit
required: Any => Unit
inputArgs.map(x => obsKPI(x._1, x._2))
^
Thanks for letting me know what went wrong in here.
Functions aren't covariant in their parameter types (they are in fact contravariant).
This means, that if Foo is a subclass of Bar, Foo => Unit is not a subclass of Bar => Unit (the opposite is true).
In your case, you are trying to coerce func1 and func2 to Any => Unit, but that cannot work, because their types are incompatible - one is String => Unit, and the other one is Int => Unit.
One way to get around this problem, is to use a case class rather than a tuple:
case class KPI[T](t: Option[T], f: T => Unit)
def obsKPI(kpi: KPI[_]) = kpi match {
case KPI(Some(k), f) => f(k)
case _ => () // `()` is the value of type Unit. Unit, as you had it is the value of type Unit.type - not what you want at all
}
// You can also write the above more concise like this: def obsKPI[T](kpi: KPI[T]) = kpi.t.foreach(kpi.f)
def func1(str:String) = println(str)
def func2(num: Int) = println(num)
val inputArgs = List(KPI(Some("first"),func1 _), KPI(Some(456), func2 _), KPI(Some("third"), func1 _), KPI[Int](None,func2 _))
inputArgs.foreach(obsKPI) // Could do .map here too, but ending up with a list of ()s is unlikely what you you want.
You can make it look a bit more elegant, if you make your obsKPI into a member of the case class:
case class KPI[T](t: Option[T], f: T => Unit) {
def obs = t.foreach(f)
}
val inputArgs = List(KPI(Some("first"),func1 _), KPI(Some(456), func2 _), KPI(Some("third"), func1 _), KPI[Int](None,func2 _))
inputArgs.foreach(_.obs)

Can we have an array of by-name-parameter functions?

In Scala we have a by-name-parameters where we can write
def foo[T](f: => T):T = {
f // invokes f
}
// use as:
foo(println("hello"))
I now want to do the same with an array of methods, that is I want to use them as:
def foo[T](f:Array[ => T]):T = { // does not work
f(0) // invokes f(0) // does not work
}
foo(println("hi"), println("hello")) // does not work
Is there any way to do what I want? The best I have come up with is:
def foo[T](f:() => T *):T = {
f(0)() // invokes f(0)
}
// use as:
foo(() => println("hi"), () => println("hello"))
or
def foo[T](f:Array[() => T]):T = {
f(0)() // invokes f(0)
}
// use as:
foo(Array(() => println("hi"), () => println("hello")))
EDIT: The proposed SIP-24 is not very useful as pointed out by Seth Tisue in a comment to this answer.
An example where this will be problematic is the following code of a utility function trycatch:
type unitToT[T] = ()=>T
def trycatch[T](list:unitToT[T] *):T = list.size match {
case i if i > 1 =>
try list.head()
catch { case t:Any => trycatch(list.tail: _*) }
case 1 => list(0)()
case _ => throw new Exception("call list must be non-empty")
}
Here trycatch takes a list of methods of type ()=>T and applies each element successively until it succeeds or the end is reached.
Now suppose I have two methods:
def getYahooRate(currencyA:String, currencyB:String):Double = ???
and
def getGoogleRate(currencyA:String, currencyB:String):Double = ???
that convert one unit of currencyA to currencyB and output Double.
I use trycatch as:
val usdEuroRate = trycatch(() => getYahooRate("USD", "EUR"),
() => getGoogleRate("USD", "EUR"))
I would have preferred:
val usdEuroRate = trycatch(getYahooRate("USD", "EUR"),
getGoogleRate("USD", "EUR")) // does not work
In the example above, I would like getGoogleRate("USD", "EUR") to be invoked only if getYahooRate("USD", "EUR") throws an exception. This is not the intended behavior of SIP-24.
Here is a solution, although with a few restrictions compared to direct call-by-name:
import scala.util.control.NonFatal
object Main extends App {
implicit class Attempt[+A](f: => A) {
def apply(): A = f
}
def tryCatch[T](attempts: Attempt[T]*): T = attempts.toList match {
case a :: b :: rest =>
try a()
catch {
case NonFatal(e) =>
tryCatch(b :: rest: _*)
}
case a :: Nil =>
a()
case Nil => throw new Exception("call list must be non-empty")
}
def a = println("Hi")
def b: Unit = sys.error("one")
def c = println("bye")
tryCatch(a, b, c)
def d: Int = sys.error("two")
def e = { println("here"); 45 }
def f = println("not here")
val result = tryCatch(d, e, f)
println("Result is " + result)
}
The restrictions are:
Using a block as an argument won't work; only the last expression of the block will be wrapped in an Attempt.
If the expression is of type Nothing (e.g., if b and d weren't annotated), the conversion to Attempt is not inserted since Nothing is a subtype of every type, including Attempt. Presumably the same would apply for an expression of type Null.
As of Scala 2.11.7, the answer is no. However, there is SIP-24, so in some future version your f: => T* version may be possible.

How to convert recursion to fold

According to Erik Meijer, as functional programmers, we all know that instead of recursion, we should use fold. How do you convert the following to use fold? I can see one way with return, but return should also be avoided in fp. Thanks!
def tryOld(string: String, original: Exception, zomOldList: List[String => Double]): Double = {
zomOldList match {
case Nil =>
throw original
case head :: tail =>
try {
head(string)
} catch {
case ex: Exception =>
tryOld(string, original, tail)
}
}
}
You can implement this with foldRight taking advantage of functions being values:
import util.control.NonFatal
def tryOld(string: String, original: Exception, zomOldList: List[String ⇒ Double]): Double = {
val unhandled: String ⇒ Double = _ ⇒ throw original
zomOldList.foldRight(unhandled) { (f, z) ⇒
x ⇒ try { f(x) } catch { case NonFatal(_) ⇒ z(x) }
}(string)
}
Note we use NonFatal here to avoid catching exceptions that we shouldn't be catching. You can write this in a more elegant way by not using exceptions directly.
You cannot implement this with a fold. A fold loops over every element of a collection, whereas tryOld will sometimes terminate early. You could take advantage of Stream's laziness and implement it in terms of collectFirst and Try:
import scala.util.Try
def tryOld(string: String, original: Exception, zomOldList: List[String => Double]): Double =
zomOldList.toStream.map(x => Try(x(string))) collectFirst {
case Success(x) => x
} getOrElse (throw original)
but your original recursive implementation is clearer and more performant.
EDIT:
If Scala had a foldRight with the same laziness properties as Haskell's foldr, then this could be defined in terms of foldRight:
implicit class GiveStreamAWorkingFoldRight[A](val s: Stream[A]) extends AnyVal {
def lazyFoldRight[B](z: => B)(f: (A, () => B) => B): B =
if (s.isEmpty) z else f(s.head, () => s.tail.lazyFoldRight(z)(f))
}
def tryOld(string: String, original: Exception, zomOldList: List[String => Double]): Double =
zomOldList.toStream.lazyFoldRight(throw original) { (a, b: () => Double) =>
try {
a(string)
} catch {
case ex: Exception => b()
}
}
However, Scala's lack of true tail-call optimization means that each call to b will introduce a new stack frame, potentially leading to a stack overflow.
Here's a solution with foldLeft. It is lengthy since I first wrote a generic function which is called by tryOldString
def tryOld[In, Error, Out](
in: In,
original: Error,
zomOldList: List[In => Either[Error, Out]]
): Either[Error, Out] = {
val seed: Either[Error, Out] = Left(original)
zomOldList.foldLeft(seed) {
case (prev, f) =>
// stores first match without return
if (seed != prev) {
prev
} else {
f(in).fold(
fa =>
prev,
fb =>
Right(fb)
)
}
}
}
def tryOutString(string: String, original: Exception, zomOldList: List[String => Double]): Double = {
val zomFunctions: List[String => Either[Exception, Double]] = zomOldList.map {
f =>
s: String =>
try {
Right(f(s))
} catch {
case e: Exception =>
Left(e)
}
}
tryOld(string, original, zomFunctions).fold(
bad => throw original,
good => good
)
}

Optional function parameter with generic return type

How would you implement class that parses some input via regex and transforms founded string to some other type? My approach is:
class ARegex[T](regex:Regex, reform:Option[String => T]){
def findFirst(input:String):Option[T] = {
(regex.findFirstIn(input), reform) match{
case (None, _) => None
case (Some(s), None) => Some(s) // this won't compile because of type mismatch
case (Some(s), Some(fun)) => Some(fun(s))
}
}
}
class BRegex[T](regex:Regex, reform:Option[String => T]) {
def findFirst(input:String) = { //returns Option[Any] - erasure
(regex.findFirstIn(input), reform) match{
case (None, _) => None
case (Some(s), None) => Some(s)
case (Some(s), Some(fun)) => Some(fun(s))
}
}
}
We can solve this problem by eliminating the Option part of the reform's type, and using a different mechanism to indicate that we don't want to change the match in any way. This mechanism is to use identity as a default parameter or pass identity when you don't want the type to change.
class ARegex[T](regex:Regex, reform:String => T = identity[String](_)){
def findFirst(input:String):Option[T] = {
regex.findFirstIn(input) match{
case None => None
case Some(s) => Some(reform(s))
}
}
}
new ARegex("something".r).findFirst("something else") //returns Option[String]
new ARegex("3".r, {x=>x.toInt}).findFirst("number 3") //returns Option[Int]
Well, the problem is the type mismatch, because you are returning either a String or a T, which, of course, are unified at Any. You can't say you are going to return Option[T] and then return Option[String].
Other than that, a simplified version of that code is this:
class ARegex[T](regex: Regex, reform: Option[String => T]) {
def findFirst(input: String): Option[Any] =
regex findFirstIn input map { s => reform map (_(s)) getOrElse s }
}
You could return an Option[Either[String, T]], though. The code would look like this:
class ARegex[T](regex: Regex, reform: Option[String => T]) {
def findFirst(input: String): Option[Either[String, T]] =
regex findFirstIn input map { s => reform map (_(s)) toRight s }
}
Why is reform Option[String => T] instead of just String => T? If you don't pass in a mechanism for creating an instance of your desired type, there's no mechanism for the runtime system to actually create the appropriate object. If you really need to pass in an Option[String => T] then your second case should simply return None.
Also, flatMap is your friend, and will give you the correct behavior (i.e. if reform is None, the method returns None.
class RegexExtractor[T](regex: Regex, reform: Option[String => T]) {
def findFirst(input: String): Option[T] = reform.flatMap(f => regex.findFirstIn(input).map(f))
}