Replace Asynchronous Anonymous Class with Function - scala

I am thinking this may be possible with the shapeless library.
I'm using the shapeless to convert an anonymous class to a closure. This requires the use of hlisted from the FnHListerAux trait.
All I want to do is get rid of the dummy function passed in and return a closure around this function which has the same type signature as F. This would be easy if there wasn't an asynchronously executed anonymous class. Is there a way to get around this?
def async[F, A <: HList, R](
shell: Shell,
success: F,
failure: FunctionTypes.Failure,
dummy: F)(implicit h: FnHListerAux[F, A => R],
u: FnUnHListerAux[A => R, F]): F =
{ (args: A) =>
require(shell != null, "Shell cannot be null")
require(shell.getDisplay() != null, "The shell must have a display")
val display = shell.getDisplay()
display.asyncExec(new Runnable() {
def run(): Unit = {
try {
success.hlisted(args)
} catch {
case e: Throwable =>
failure(e)
}
}
})
dummy.hlisted(args)
}.unhlisted

I'll start by simplifying a bit. Suppose I have a function f. I don't know it's arity in advance, and I don't care about what it returns. I want to wrap it with some functionality and get a function with the same argument types. I also don't care what this resulting function returns, so I may as well have it return Unit.
You could write a bunch (well, 22) of functions like the following:
def wrap[A](f: A => Unit): A => Unit = ???
def wrap[A, B](f: (A, B) => Unit): (A, B) => Unit = ???
def wrap[A, B, C](f: (A, B, C) => Unit): (A, B, C) => Unit = ???
But you don't want to.
Shapeless can definitely help you solve this problem more generically:
def wrap[F, A <: HList](f: F)(
implicit h: FnHListerAux[F, A => Unit], u: FnUnHListerAux[A => Unit, F]
): F = { (args: A) =>
println("Before!"); f.hlisted(args); println("After!")
}.unhlisted
Which gives us:
scala> def f(i: Int, s: String) { println(s * i) }
f: (i: Int, s: String)Unit
scala> val wf = wrap(f _)
wf: (Int, String) => Unit = <function2>
scala> wf(3, "ab")
Before!
ababab
After!
Note that f could return something other than Unit and this would still work, since everything in Scala is a Unit and the FunctionN traits are covariant in their return type.
Applying this approach to your code, we get the following:
def async[F, A <: HList](
shell: Shell, success: F, failure: FunctionTypes.Failure
)(
implicit h: FnHListerAux[F, A => Unit], u: FnUnHListerAux[A => Unit, F]
): F = { (args: A) =>
require(shell != null, "Shell cannot be null")
require(shell.getDisplay() != null, "The shell must have a display")
val display = shell.getDisplay()
display.asyncExec(new Runnable() {
def run(): Unit = {
try {
success.hlisted(args)
} catch {
case e: Throwable =>
failure(e)
}
}
})
}.unhlisted
No dummy required.

Related

Scala: Create custom OptionT monad from cats for learning

we are creating our own OptionT of cats for understanding, how monads are work and monads transformation flow. While creating our own custom monad getting some of the errors. First thing below is our code:
case class WhateverOpt[W[_], A] (value: W[Option[A]]) {
def map[B] (f: A => B) (implicit M: Monad[W]): WhateverOpt[W, B] =
WhateverOpt(M.map(value)(_.map(f)))
def flatMap[B] (f: A => WhateverOpt[W, B]) (implicit M: Monad[W]): WhateverOpt[W, B] =
WhateverOpt(M.flatMap(value)(optA => optA match {
case Some(v) => f(v).value
}))
}
implicit val optionTMonad = new Monad[Option] {
override def map[A, B](fa: Option[A])(f: A => B): Option[B] = fa.map(f)
override def flatMap[A, B](fa: Option[A])(f: A => Option[B]): Option[B] = fa.flatMap(f)
}
val optionResult = for {
user <- WhateverOpt(repository.getUserOption(1))
addres <- WhateverOpt(repository.getAddressOption(user))
} yield addres.city
Below are the points, where we stuck:
How to handle None case in WhateverOpt flatMap method?
When executing the code, getting runtime error:
Error:(26, 12) could not find implicit value for parameter M: usercases.mtransfomer.Monad[scala.concurrent.Future]
addres <- WhateverOpt(repository.getAddressOption(user))
We are not sure about the error because we are creating optionTMonad implicit and by default, all are in the same scope. How can we resolve these two issues?
Update
Full code is available on Github branch https://github.com/harmeetsingh0013/fp_scala/blob/master/src/main/scala/usercases/mtransfomer/Example5.scala
About how to deal with None:
case class WhateverOpt[W[_], A] (value: W[Option[A]]) {
def map[B] (f: A => B) (implicit M: Monad[W]): WhateverOpt[W, B] =
WhateverOpt(M.map(value)(_.map(f)))
def flatMap[B]
(f: A => WhateverOpt[W, B])
(implicit wMonad: Monad[W])
: WhateverOpt[W, B] = {
WhateverOpt(wMonad.flatMap(value) { (oa: Option[A]) =>
oa match {
case None => wMonad.pure(None)
case Some(a) => f(a).value
}
})
}
}
Imagine for a second that W is Future. Then the above code says:
wait until the wrapped value yields a result oa of type Option[A]
If oa turns out to be None, then there is nothing we can do, because we cannot obtain any instances of type A in order to call f. Therefore, immediately return None. The immediately return is the pure-method of the Future-monad, so for the general case we have to invoke wMonad.pure(None).
If oa yields Some(a), we can give this a to f, and then immediately unpack it to get to the value of type W[Option[B]].
Once we have the W[Option[B]] (whether empty or not), we can wrap it into WhateverOpt and return from the flatMap method.
I assume that you wanted to reimplement Monad[Option] just for fun (it's already in the library (the catsStdInstancesForOption thing is a CommutativeMonad), but here is how you could re-build it:
implicit val optionTMonad = new Monad[Option] {
override def map[A, B](fa: Option[A])(f: A => B): Option[B] = fa.map(f)
def flatMap[A, B](fa: Option[A])(f: A => Option[B]): Option[B] = fa.flatMap(f)
def pure[A](a: A): Option[A] = Some(a)
def tailRecM[A, B](a: A)(f: (A) => Option[Either[A, B]]): Option[B] = {
f(a) match {
case Some(Left(nextA)) => tailRecM(nextA)(f)
case Some(Right(res)) => Some(res)
case None => None
}
}
}
Notice that 1.0.1 requires to implement pure and tailRecM, and does not provide default implementations for that.
I don't want to say much about the necessary imports for future, but the latest version has cats.instances.future which provides a Monad instance. Check this again, because it seems as if you are using a different version of cats (your version didn't complain because of the missing tailRecM in your Option-monad).
How to handle None case in WhateverOpt flatMap method?
This answer is already explained by #Gabriele Petronella and #Andrey Tyukin with details.
When executing the code, getting runtime error: Error:(26, 12) could
not find implicit value for parameter M:
usercases.mtransfomer.Monad[scala.concurrent.Future] addres <-
WhateverOpt(repository.getAddressOption(user))
This error occurs, because In WhateverOpt constructor we know that our value is W[Option[A]], where Option is already defined and handle by the code, but repository.getUserOption(1) return Future[Option[User]] where Future is handled by generic parameter W and in that, case, we need to define, how to handle monads for Future. For resolving that issue, we need to implement new Monad[Future] rather than, new Monad[Option] as below:
case class WhateverOpt[W[_], A] (value: W[Option[A]]) {
def map[B] (f: A => B) (implicit M: Monad[W]): WhateverOpt[W, B] =
WhateverOpt(M.map(value)(_.map(f)))
def flatMap[B] (f: A => WhateverOpt[W, B]) (implicit M: Monad[W]): WhateverOpt[W, B] =
WhateverOpt(M.flatMap(value)(optA => optA match {
case Some(v) => f(v).value
case None => M.pure(None)
}))
}
implicit val futureMonad = new Monad[Future] {
override def pure[A](a: A): Future[A] = Future.successful(a)
override def map[A, B](fa: Future[A])(f: A => B): Future[B] = fa.map(f)
override def flatMap[A, B](fa: Future[A])(f: A => Future[B]): Future[B] = fa.flatMap(f)
}
val optionResult: WhateverOpt[Future, String] = for {
user <- WhateverOpt(repository.getUserOption(1))
addres <- WhateverOpt(repository.getAddressOption(user))
} yield addres.city
I am not sure about my disription, which I mention in answere, but current my assumptions are this and for me above code is working fine. For a complete example, please click on the GitHub repo, which is mention in the question.
How to handle None case in WhateverOpt flatMap method?
When you flatMap over None you return None. When you flatMap over WhateverOpt[W[_], B] you want to return the pure of it, which in your code would be M.pure(None).
When executing the code, getting runtime error: Error:(26, 12) could not find implicit value for parameter M: usercases.mtransfomer.Monad[scala.concurrent.Future]
addres <- WhateverOpt(repository.getAddressOption(user))
That's a compile-time error (not a runtime one) and it's due to the missing instance of Monad[Future]. In order to get an instance of Monad[Future] in scope with cats, you can do:
import cats.instances.future._
import scala.concurrent.ExecutionContext.Implicits.global
Also, you can avoid declaring your own Monad[Option] by importing it from cats with
import cats.instances.option._

writing generic function using method name

I am trying to write the following method:
case class Config2(repoName: String)
def buildAction[A, M, R <: HList]()
(implicit
gen: Generic.Aux[Config2, R],
mod: Modifier.Aux[R, M, A, A, R])
: (A, Config2) => Config2 = {
(arg: A, c: Config2) => {
val rec = mod.apply(gen.to(c), _ => arg)
gen.from(rec)
}
}
When trying to use it with:
buildAction[String, Witness.`'repoName`.T, String :: HList]()
I get an error:
could not find implicit value for parameter gen: shapeless.Generic.Aux[com.advancedtelematic.tuf.cli.Cli.Config2,shapeless.::[String,shapeless.HList]]
[error] val _ = buildAction[String, Witness.`'repoName`.T, String :: HList]()
am I missing some import here?
Second question is, can I somehow rewrite this signature so I don't don't have to specify all the types? In practive the Config2 type takes a long list of fields so it's not pratical to write this all the time
Update:
I simplified this to the following:
val CGen = LabelledGeneric[Config]
def buildAction[A, M]()
(implicit mod: Modifier.Aux[CGen.Repr, M, A, A, CGen.Repr])
: (A, Config) => Config = {
(arg: A, c: Config) => {
val rec = mod.apply(CGen.to(c), _ => arg)
CGen.from(rec)
}
}
Which allows me to just write:
buildAction[String, Witness.`'repoName`.T]()
But I still have to specify that Witness. Is the a way I could write buildAction[String]("repoName") and have some method provide the Witness implicitly?
Update: the following works!
val CGen = LabelledGeneric[Config]
def buildAction[A](witness: Witness)
(implicit mod: Modifier.Aux[CGen.Repr, witness.T, A, A, CGen.Repr]):
(A, Config) => Config = {
(arg: A, c: Config) => {
val rec = mod.apply(CGen.to(c), _ => arg)
CGen.from(rec)
}
}
buildAction[RepoName]('repoName)
am I missing some import here?
No, it's probably just that String :: HList must be String :: HNil
Second question is, can I somehow rewrite this signature so I don't don't have to specify all the types?
You can use a trick known as kinda-curried type parameters:
object buildAction {
class PartiallyApplied[A, M] {
def apply[R <: HList]()(implicit ...)
}
def apply[A, M] = new PartiallyApplied[A, M]
}
Used as
buildAction[String, Witness.`'foo`.T]()
Also, since your code mentions field name, you probably want LabelledGeneric in conjunction with ops.record.Updater

Scala: How to use Functors for multi type parameter trait

I have and ADT which is basically a wrapper over Function1:
case class Abstract[M[_], A, B](f:M[A] => M[B]) {
def fn: M[A] => M[B] = { case x: M[A] => f(x) }
}
I want to map over these, so I defined a Functor like so:
trait AbstractAPI[E] {
type AbsO[T] = Abstract[List, E, T]
// type AbsO[T] = Abstract[List, _, T] => does not work (?)
implicit val abstractO: Functor[AbsO] = new Functor[AbsO] {
def map[A, B](fa: AbsO[A])(f: A => B): AbsO[B] = {
new Abstract(fa.fn andThen { x: List[A] => x.map{ y => f(y) } })
}
}
}
Now, to actually map over an Abstract, I'd need AbstractAPI[Int], like
case object IntAbstractAPI extends AbstractAPI[Int]
object A {
import IntAbstractAPI._
val f:List[Int] => List[String] = { case x: List[Int] => x.map{ _.toString.toLowerCase } }
val hey = (new Abstract(f)).map{ x => x.toInt }
}
or
object A extends AbstractAPI[Int] {
val f:List[Int] => List[String] = { case x: List[Int] => x.map{ _.toString.toLowerCase } }
// FINALLY!
val res = (new Abstract(f)).map{ x => x.toInt }.map{ _.toFloat + 10f }
// Abstract[List, Int, Float] = Abstract(<function1>)
}
However, in this pattern, I'd have to define case objects for every possible E. Here are my questions:
Is this the correct way to use Functors?
How can I automate the creation of the case objects for every possible E (or make the compiler infer it?)
Edit 1:
Further clarification: The above implementation works, but this one does not:
object A extends AbstractAPI {
val f:List[Int] => List[String] = { case x: List[Int] => x.map{ _.toString.toLowerCase } }
val res = (new Abstract(f)).map{ x => x.toInt }.map{ _.toFloat + 10f }
// Abstract[List, Int, Float] = Abstract(<function1>)
}
gives compilation error:
value map is not a member of Abstract[List,Int,String]
I assume this is because the compiler is not able to derive a functor for Abstract[List,Int,String]?
You can derive a functor for type parameters that you don't care about.
import cats.Functor
import cats.syntax.functor._
And I'll rename second type parameter on Abstract to X, it'll help
case class Abstract[M[_], X, A](f: M[X] => M[A]) // forget the fn bit for now
You can create typeclass instances not only with a val, but also with a def. It is allowed to have type parameters and also take other implicit (but only implicit) parameters.
type Abs1[X] = ({ type L[A] = Abstract[List, X, A] })
/*implicit*/ def abstract1[X]: Functor[Abs1[X]#L] = new Functor[Abs1[X]#L] {
override def map[A, B](fa: Abstract[List, X, A])(f: A => B): Abstract[List, X, B] =
Abstract(mx => fa.f(mx).map(f))
}
If map is all you need from a List, you can generalize further for any M[_] that has a Functor instance. Also placing it into a companion object of Abstract enables it to be found without additional imports / inheritance / etc.
object Abstract {
// Abstract.MX[M, X]#L can be replaced with Abstract[M, X, ?] if you use kind-projector
type MX[M[_], X] = ({ type L[A] = Abstract[M, X, A] })
implicit def genericFunctor[M[_]: Functor, X] = new Functor[MX[M, X]#L] {
override def map[A, B](fa: Abstract[M, X, A])(f: A => B): Abstract[M, X, B] =
Abstract(mx => fa.f(mx).map(f)) // the implementation is the same
}
}
And it works, if you import instances for whatever your M[_] is
assert {
import cats.instances.list._ // get Functor[List]
// map is automatically picked up from Functor[Abstract[List, Int, ?]]
Abstract(identity[List[Int]])
.map(Vector.range(0, _))
.map(_.mkString(""))
.f(List(1, 2, 3)) == List("0", "01", "012")
}
assert {
import cats.instances.option._
Abstract(identity[Option[Int]])
.map(_ min 42)
.map(i => Range(i, i + 3))
.f(Some(11)) == Some(Range(11, 14))
}
You can try the code there
Answering your second question, you could try this implicit AbstractAPI[T] factory:
implicit def abstractAPI[T]: AbstractAPI[T] = new AbstractAPI[T] {}
Any required implicit evidence for AbstractAPI[T] should work, e.g:
def f[T : AbstractAPI]: Unit = ()
f

Is it possible to use a fixed constant instance of Failure as Try[B] for any B without casting?

While thinking about my previous question, I realized I ought to be able to write something like the following:
val empty: Try[B, forall types B] = Failure(new RuntimeException("empty"))
def firstSuccess[A, B](xs: Iterable[A], f: A => Try[B]): Try[B] = {
xs.foldLeft(empty)((e, a) => e.recoverWith { case _ => f(a) })
}
because a Failure is a valid Try[B] for any type B. Is there a way to achieve my "B, forall types B" in Scala?
You can use the Nothing type since everything in scala is Nothing:
val empty = Failure[Nothing](new RuntimeException("empty"))
def firstSuccess[A, B](xs: Iterable[A], f: A => Try[B]): Try[B] = {
xs.foldLeft[Try[B]](empty)((e, a) => e.recoverWith { case _ => f(a) })
}
You do have to sprinkle in a few types here and there though (added type parameter to foldLeft).

Type checker in trouble over #specialized

The trait below compiles fine without the #specialized annotations, or without the map method. Otherwise, it will fail with a compilation error, which doesn't make a lot of sense (at least to me):
[error] (compile:compile) scala.tools.nsc.symtab.Types$TypeError: type mismatch;
[error] found : U(in method foreach)(in method foreach)
[error] required: U(in method foreach)(in method foreach)
This is the trait that I'm talking about:
trait Tuple2Traversable[#specialized(Int, Byte) +A, #specialized(Int, Byte) +B] {
def foreach[T](fn: (A, B) => T)
def map[T](fn: (A, B) => T): Traversable[T] = new Traversable[T] {
def foreach[U](f: T => U) {
def composed(a: A, b: B) = f(fn(a, b))
Tuple2Traversable.this.foreach(composed)
}
}
def flatMap[T](fn: (A, B) => Traversable[T]): Traversable[T] = new Traversable[T] {
def foreach[U](f: (T) => U) {
def composed(a: A, b: B) = fn(a, b).foreach(f)
Tuple2Traversable.this.foreach(composed)
}
}
def filter(included: (A, B) => Boolean): Tuple2Traversable[A, B] = new Tuple2Traversable[A, B] {
def foreach[T](fn: (A, B) => T) {
def composed(a: A, b: B) = if (included(a, b)) fn(a, b)
Tuple2Traversable.this.foreach(composed)
}
}
def foldLeft[T](z: T)(fn: (T, A, B) => T): T = {
var current = z
def op(a: A, b: B) {
current = fn(current, a, b)
}
foreach(op)
current
}
def asTraversable = new Traversable[(A, B)] {
def foreach[U](f: ((A, B)) => U) {
def tupled(a: A, b: B) = f((a, b))
Tuple2Traversable.this.foreach(tupled)
}
}
}
I've been staring at this for a while now. Any suggestions on how to solve this would be highly appreciated.
Perhaps I should add that the purpose of this class is to have a Traversable of tuples, without forcing those tuples to ever be created. A Traversable[(A,B)] would accept a Tuple2[A,B] => T as the parameter of foreach. I want my 'traversable' to accept a function (A, B) => T. (Like def fn(a: Int, b: Int) = a + b.)
Looks like some internal compiler bug. I get the same error in scala 2.9.2, but it compiles fine in scala 2.10-RC2