scala lifting function having with a collection as argument - scala

I have a class which accepts a function f: Option[Seq[Option[A]]] => Option[A]]
case class Function[A](operator: Option[Seq[Option[A]]] => Option[A], name: String, arity: Int)
What i would like is for the user of this class to be able to not have to worry about the Option framework. So the user would pass a function g: Seq[A] => A and under the hood i would lift that function. The lifting part is what i'm not being able to do.
This is what i have (using optionInstance.lift of scalaz) :
object Function {
def apply[A](operator: Seq[A] => A) = new Function(optionInstance.lift(operator),"a", 1)
}
However this does not compile since the lift operator is returning Option[Seq[A]] instead of Option[Seq[Option[A]]]. How can this be done?

Here's an example of how to convert between your two prototypes :
def f[A]: Seq[A] => A = ???
def g[A]: Option[Seq[Option[A]]] => Option[A] = {
{
case None => None
case Some(seq) if seq.exists(_.isEmpty) => None
case Some(seq) => Some(f(seq.flatten))
}
}
You can use this to transform your operator

If you would like to return Option[Seq[Option[A]]] you have to first transform your Seq[A] into a Seq[Option[A]] before doing the lift

Related

scala syntax explanation involving higher order functions, type parameter and return type

I am having problems understanding the Scala syntax, please advice. I have two snippets of code.
abstract class Try[T] {
def flatMap[U](f: T => Try[U]): Try[U] = this match {
case Success(x) => try f(x) catch { case NonFatal(ex) => Failure(ex) }
case fail: Failure => fail
}
}
My understanding:
flatMap received as parameter a function f. In turn this function f
receives type parameter T and returns Try of type parameter U.
flatMap ultimately return Try of type parameter U.
Q1 - Is my understanding correct?
Q2 - what is the relation between the return type from f (namely Try[U]) and the return type of flat map Try[U]? Does it have to be the same?
def flatMap[U](f: T => Try[U]): Try[U]
Or can I somehow have something like
def flatMap[U](f: T => Option[U]): Try[U]
In the last snippet of code, I guess that, after I use the function f inside my flatMap, I would need to make the connection between the output of f (namely Option[U]) and the final output demanded by flatMap (I mean Try[U])
EDIT
This code is taken from a scala course. here is the full code (some people asked about it). I just want to understand the syntax.
abstract class Try[T] {
def flatMap[U](f: T => Try[U]): Try[U] = this match {
case Success(x) => try f(x) catch { case NonFatal(ex) => Failure(ex) }
case fail: Failure => fail
}
def map[U](f: T => U): Try[U] = this match {
case Success(x) => Try(f(x))
case fail: Failure => fail
}
}
Q1 - Is my understanding correct?
It's hard to comment based on your sample code which has method implementation in an abstract class while no concrete classes are defined. Lets consider the following toy version of Try extracted from the Scala API with the flatMap implementation in its concrete classes:
import scala.util.control.NonFatal
sealed abstract class MyTry[+T] {
def flatMap[U](f: T => MyTry[U]): MyTry[U]
}
object MyTry {
def apply[T](r: => T): MyTry[T] =
try MySuccess(r) catch { case NonFatal(e) => MyFailure(e) }
}
final case class MyFailure[+T](exception: Throwable) extends MyTry[T] {
override def flatMap[U](f: T => MyTry[U]): MyTry[U] =
this.asInstanceOf[MyTry[U]]
}
final case class MySuccess[+T](value: T) extends MyTry[T] {
override def flatMap[U](f: T => MyTry[U]): MyTry[U] =
try f(value) catch { case NonFatal(e) => MyFailure(e) }
}
Testing it out with the following function f: T => MyTry[U] where T = String and U = Int, I hope it helps answer your question:
val f: String => MyTry[Int] = s => s match {
case "bad" => MyFailure(new Exception("oops"))
case s => MySuccess(s.length)
}
MyTry("abcde").flatMap(f)
// res1: MyTry[Int] = MySuccess(5)
MyTry("bad").flatMap(f)
// res2: MyTry[Int] = MyFailure(java.lang.Exception: oops)
Q2 - what is the relation between the return type from f (namely Try[U])
and the return type of flat map Try[U]? Does it have to be the same?
In Scala, flatMap is a common method defined in many of Scala containers/collections such as Option[T], List[T], Try[T], Future[T], with a standard signature:
class Container[T] {
def flatMap[U](f: T => Container[U]): Container[U]
}
If you want to have a special map that takes a T => Container1[U] function and returns a Container2[U], it'd probably best not to name it flatMap.
Q1 Largely correct, but just to clarify, all of this happens at compile time - T is not known at runtime (see here)
Q2 Of course you can create a method with signature
...[U](f: T => Option[U]): Try[U]
and you're free to call that method flatMap, but it won't be a standard flatMap:
trait T[A] {
flatMap[B](f: A => T[B]): T[B]
}
There are mathematical reasons for the form of flatMap (which also have implications in Scala's implementation of for expressions). To avoid confusion ...
Rather than altering flatMap's signature, wrap your T => Option[U] with an Option[U] => Try[U] to create a T => Try[U] before passing it to flatMap.

Monad transformer flatMap working

I´ve been playing monad transformer, and I just create one Future[Option]. But after read some blogs there´s something that is not explained and I don't understand.
Here in the implementation of my map and flatMap, in the flatMap once that I get the value of my option, and I apply the function over the value, I have to invoke over the function f(a) the .Value_passed_in_the_case_class(in this case future)
case class FutOpt[A](future: Future[Option[A]]) {
def map[B](f: A => B): FutOpt[B] = {
FutOpt(future.map(option => option.map(value => f(value)))
.recoverWith {
case e: Exception =>
Future.successful(Option.empty)
})
}
def flatMap[B](f: A => FutOpt[B]): FutOpt[B] =
FutOpt(future.flatMap(option => option match {
case Some(a) => f(a).future --> WHAT THIS .future IS DOING?
case None => Future.successful(None)
}))
}
What is happening there?, and how works?.
Regards.
What is happening there?
flatMap expects you to return it a FutOpt[B]:
def flatMap[B](f: A => FutOpt[B]): FutOpt[B]
The signature of your case class requires you to pass in a Future[Option[A]]:
case class FutOpt[A](future: Future[Option[A]])
This line of code:
FutOpt(future.flatMap(option => option match {
case Some(a) => f(a).future
Is constructing a new instance of FutOpt[B], and it needs a value of type Future[Option[B]] in order to be able to construct itself properly. f(a) returns a FutOpt[B], not a Future[Option[B]], and that is why it needs to access .future, which is of type Future[Option[B]].

Handling Option[A] in a function

I need a function which does something like the code below
def function[A,B](a: Option[A], f: Function[A,B]) = {
a match {
case None => None
case Some(v) => Some(f(v))
}
}
Is there any scala built-in function which does the same?
def function[A,B](a: Option[A], f: Function[A,B]) = {
a.map(f(_))
}
Option can be treated as a Monad so many operations such as map, flatMap, and filter are available on it.
http://www.scala-lang.org/api/current/index.html#scala.Option

Scala: How do I write the type of the function that sortBy takes?

I want to pass the parameter that List.sortBy takes through to another function. My code looks something like this:
//Scala
def sortAndMore(list: List[(String, _)], sortFn: Option[???] = None) = {
val maybeSortedList = sortFn match {
case None => list
case Some(fn) => list.sortBy(fn)
}
// do some more stuff with this list
}
val myList = ("one", 1)::("three", 3)::("two", 2)::Nil
sortAndMore(myList, Some(_._1 /*???*/))
So in the end I want to have the same result as this gives:
myList.sortBy(_._1)
What is the type of Option in the sortAndMore function?
The Scala API for scala.collection.immutable.List says this:
def sortBy [B] (f: (A) ⇒ B)(implicit ord: Ordering[B]): List[A]
I tried several things, but I just don't know the correct syntax, and wasn't lucky guessing it. Any hints are very much appreciated, especially with a pointer to why the syntax has to be that way.
Here is my solution (compiles on my terminal)
def sortAndMore(list: List[(String,_)], sortFn: Option[((String,_))=>String] = None) = {
val maybeSortedList = sortFn match {
case Some(fn) => list.sortBy(fn)
case None => list
}
}
sortAndMore(myList, Some(_._1))

Folding on case classes

I have a situation where I have a couple of case classes where all of their variables are optional.
Let's say I have:
case class Size(width: Option[Int], height: Option[Int])
case class Foo(a: Option[String], b: Option[Boolean], c: Option[Char])
Given a collection of the same type of case class I would like to fold over them comparing the option values and keep the values which are defined. I.e. for Size:
values.foldLeft(x) { (a, b) =>
Size(a.width.orElse(b.width), a.height.orElse(b.height))
}
I would like to do this in a more general way for any of the case classes like the ones above. I'm thinking about doing something with unapply(_).get etc. Does anyone know a smart way to solve this?
Ok, consider this:
def foldCase[C,T1](unapply: C => Option[Option[T1]], apply: Option[T1] => C)
(coll: Seq[C]): C = {
coll.tail.foldLeft(coll.head) { case (current, next) =>
apply(unapply(current).get orElse unapply(next).get)
}
}
case class Person(name: Option[String])
foldCase(Person.unapply, Person.apply)(List(Person(None), Person(Some("Joe")), Person(Some("Mary"))))
One could overload foldCase to accept two, three, or more parameters, one version of f for each arity. It could then be used with any case class. Since there's the tuple-thing to worry about, below's one way to make it work with case classes or two parameters. Expanding it to more parameters is then trivial, though a bit tiresome.
def foldCase[C,T1,T2](unapply: C => Option[(Option[T1], Option[T2])], apply: (Option[T1], Option[T2]) => C)
(coll: Seq[C]): C = {
def thisOrElse(current: (Option[T1], Option[T2]), next: (Option[T1], Option[T2])) =
apply(current._1 orElse next._1, current._2 orElse next._2)
coll.tail.foldLeft(coll.head) { case (current, next) =>
thisOrElse(unapply(current).get, unapply(next).get)
}
}
val list = Person(None, None) :: Person(Some("Joe"), None) :: Person(None, Some(20)) :: Person(Some("Mary"), Some(25)) :: Nil
def foldPerson = foldCase(Person.unapply, Person.apply) _
foldPerson(list)
To use it overloaded, just put all definitions inside one object:
object Folder {
def foldCase[C,T1](unapply: C => Option[Option[T1]], apply: Option[T1] => C)
(coll: Seq[C]): C = {
coll.tail.foldLeft(coll.head) { case (current, next) =>
apply(unapply(current).get orElse unapply(next).get)
}
}
def foldCase[C,T1,T2](unapply: C => Option[(Option[T1], Option[T2])], apply: (Option[T1], Option[T2]) => C)
(coll: Seq[C]): C = {
def thisOrElse(current: (Option[T1], Option[T2]), next: (Option[T1], Option[T2])) =
apply(current._1 orElse next._1, current._2 orElse next._2)
coll.tail.foldLeft(coll.head) { case (current, next) =>
thisOrElse(unapply(current).get, unapply(next).get)
}
}
}
When you do this, however, you'll have to explicitly turn apply and unapply into functions:
case class Question(answer: Option[Boolean])
val list2 = List(Question(None), Question(Some(true)), Question(Some(false)))
Folder.foldCase(Question.unapply _, Question.apply _)(list2)
It might be possible to turn it into a structural type, so that you only need to pass the companion object, but I couldn't do it. On #scala, I was told the answer is a definitive no, at least to how I approached the problem.
[Code updated]
Here is an solution which requires only one abstract class per "arity":
abstract class Foldable2[A,B](val a:Option[A], val b:Option[B]) {
def orElse[F <: Foldable2[A,B]](that: F)(implicit ev: this.type <:< F) =
getClass.getConstructor(classOf[Option[A]], classOf[Option[B]]).newInstance(
this.a.orElse(that.a), this.b.orElse(that.b)
)
}
case class Size(w: Option[Int], h: Option[Int]) extends Foldable2(w, h)
println(Size(Some(1),None).orElse(Size(Some(2),Some(42))))
//--> Size(Some(1),Some(42))
Note that the implicit <:< argument will give a compile time error when other case classes with the same constructor arguments are passed to the method.
However, a "well formed" constructor is required, else the reflection code will blow up.
You can use productElement or productIterator (on scala.Product) to generically retrieve/iterate the elements of case classes (and tuples), but they're typed as Any, so there will be some pain.