How to lift a partial function in an Either - scala

I want to lift a partial function in an Either.
Is there a better way :
def lift[A, B, C](pf : PartialFunction[A, B])(c: A => C) : A => Either[C, B] = { a => if (pf.isDefinedAt(a)) Right(pf(a)) else Left(c(a)) }

There are lots of other ways of writing this that let you avoid the unpleasant isDefinedAt:
def lift[A, B, C](pf: PartialFunction[A, B])(c: A => C): A => Either[C, B] =
(pf andThen Right.apply) orElse (PartialFunction(c andThen Left.apply))
Or:
def lift[A, B, C](pf: PartialFunction[A, B])(c: A => C): A => Either[C, B] =
(a: A) => pf.lift(a).fold[Either[C, B]](Left(c(a)))(Right(_))
For example.
Scalaz makes the last implementation above a little nicer with its toRight:
import scalaz._, Scalaz._
def lift[A, B, C](pf: PartialFunction[A, B])(c: A => C): A => Either[C, B] =
(a: A) => pf.lift(a).toRight(c(a))
I'd probably go with some version of the orElse implementation, though.

Related

Making a partial function complete

Is there a standard way to complete a partial function PartialFunction[A, B]? Something like this:
completePartialFunction(pf: PartialFunction[A, B], z: B): A => B
or
completePartialFunction2(pf: PartialFunction[A, B], f: A => B): A => B
Yes, it's actually very simple:
def complete[A, B](pf: PartialFunction[A, B])(f: A => B): A => B =
pf.applyOrElse(_, f)
You can use lift method on PartialFunction, that returns Option[B]. So when the function is not defined for the input, None is returned. You can find more in the scaladocs.
Other solution that comes to my mind is when you're using cats or scalaz. You can then check whether the function is defined for the argument and when not, return empty from the Monoid[B] that you should pass (probably implicitly) to completePartialFunction.
If I understand the question, you want to use f() to supplement pf() so that all possible values of type A are covered.
def completePartialFunction2[A,B](pf : PartialFunction[A,B]
,f : A => B): A => B =
(a:A) => if (pf.isDefinedAt(a)) pf(a) else f(a)
Another simple version:
def completePartialFunction[A, B](pf: PartialFunction[A, B], f: A => B): A => B
= pf orElse { case a: A => f(a) }

How to Remove Explicit Casting

How do I remove explicit casting asInstanceOf[XList[B]] in Cons(f(a), b).asInstanceOf[XList[B]] inside map function? Or perhaps redesign reduce and map functions altogether? Thanks
trait XList[+A]
case object Empty extends XList[Nothing]
case class Cons[A](x: A, xs: XList[A]) extends XList[A]
object XList {
def apply[A](as: A*):XList[A] = if (as.isEmpty) Empty else Cons(as.head, apply(as.tail: _*))
def empty[A]: XList[A] = Empty
}
def reduce[A, B](f: B => A => B)(b: B)(xs: XList[A]): B = xs match {
case Empty => b
case Cons(y, ys) => reduce(f)(f(b)(y))(ys)
}
def map[A, B](f: A => B)(xs: XList[A]): XList[B] = reduce((b: XList[B]) => (a: A) => Cons(f(a), b).asInstanceOf[XList[B]])(XList.empty[B])(xs)
You can merge two argument lists into one by replacing )( by ,:
def reduce[A, B](f: B => A => B, b: B)(xs: XList[A]): B = xs match {
case Empty => b
case Cons(y, ys) => reduce(f, f(b)(y))(ys)
}
def map[A, B](f: A => B)(xs: XList[A]): XList[B] =
reduce((b: XList[B]) => (a: A) => Cons(f(a), b), XList.empty[B])(xs)
This will force the type inference algorithm to consider both first arguments of reduce before making up its mind about what B is supposed to be.
You can either widen Cons to a XList[B] at the call site by providing the type parameters explicitly:
def map[A, B](f: A => B)(xs: XList[A]): XList[B] =
reduce[A, XList[B]]((b: XList[B]) => (a: A) => Cons(f(a), b))(XList.empty[B])(xs)
Or use type ascription:
def map[A, B](f: A => B)(xs: XList[A]): XList[B] =
reduce((b: XList[B]) => (a: A) => Cons(f(a), b): XList[B])(XList.empty[B])(xs)
As a side note, reduce is traditionally more strict at the method definition than what you've written. reduce usually looks like this:
def reduce[A](a0: A, a: A): A
Implicitly requiring a non empty collection to begin with. What you've implemented is similar in structure to a foldLeft, which has this structure (from Scalas collection library):
def foldLeft[B](z: B)(op: (B, A) => B): B

Simple way to apply a list of functions to a value

Suppose I've got a list of functions List[A => B] and need a function that returns List[B] for a given value of type A:
def foo[A, B](fs: List[A => B]): A => List[B] = a => fs.map(_.apply(a))
Is there any simpler (maybe with cats) way to write List[A => B] => A => List[B] ?
As #Oleg points out, you can use Applicative to generate the function:
import cats.implicits._
def foo[A, B](fs: List[A => B]): A => List[B] = a => fs ap List(a)
Although I don't think it makes much of a difference in this particular case.
The signature of f (a -> b) -> a -> f b suggests to use flap (from Haskell).
Starting from 2.9.0 you can use its equivalent in Cats named mapApply.
import cats.implicits._
def foo[A, B](fs: List[A => B]): A => List[B] = a => fs.mapApply(a)

Transform an M[A => B] to an A => M[B]

Does there exist a utility in Scala or Scalaz to transform a container/collection of functions to a function that maps from the same input to a collection output values? The signature would look something like
def transform[M[_], A, B](m: M[A => B]): A => M[B] = ???
Here's an example implementation for the List container:
def transform[A, B](fs: List[A => B]): A => List[B] = x =>
fs.foldRight[List[B]](Nil) {
(f, acc) => f(x) :: acc
}
Ideally, this would work for any function container, including a tuple of functions, an Option[Function1[A, B]], or even a TupleN[Option[Function1[A, B]], ...].
EDIT:
I've just realized that (at least for the special case of a List) the map function works:
def transform[A, B](fs: List[A => B]): A => List[B] = x => fs map (_(x))
This can generalize to anything that has a map function with the appropriate semantics. What's the appropriate type class for this?
Assuming M is a Functor, mapply in scalaz's Functor has a similar type signature:
def mapply[A, B](a: A)(f: F[A => B]): F[B] = map(f)((ff: A => B) => ff(a))
So you could write transform in terms of that:
def transform[M[_],A,B](m: M[A => B])(implicit f:Functor[M]):A => M[B] = f.mapply(_)(m)
Edit: Another implementation using features from FunctorSyntax:
def transform[M[_]:Functor,A,B](m: M[A => B]):A => M[B] = _.mapply(m)
I searched through the Scalaz source code and it looks like Functor does the trick:
def transform[M[_]: Functor, A, B](fs: M[A => B]): A => M[B] = a => fs map (_(a))

When using an EitherT[StateWithSomeFixedStateType, T, U], how do you do some state manipulation when a left is returned?

Say you have an EitherT that looks something like this:
type StateListOfString[+T] = State[List[String], T]
type MyEitherT = EitherT[StateListOfString, Int, Boolean]
If you have a for-comprehension that could return a left:
my computation = for {
a <- thingThatCouldReturnLeft
b <- otherThingThatCouldReturnLeft
} yield b
How can you follow up with a for-comprehension that manipulates state before itself returning the left?
I think I want something very close to orElse, but orElse doesn't have access to the value of the left:
def orElse[AA >: A, BB >: B](x: => EitherT[F, AA, BB])(implicit F: Bind[F]): EitherT[F, AA, BB] = {
If it took something like (x: => Int => EitherT[F, AA, BB]) instead of just (x: => EitherT[F, AA, BB]), it would work.
I had tried starting with:
for {
a <- myComputation.isLeft
// OK, now I have something sensible, and I can follow up with something like
// a leftMap
But if I start by calling isLeft, it looks like the computation is run at least twice, once for the isLeft, and again when I call something like leftMap.
What's the right thing to use here?
Looking at the sources of orElse it seems that it can be naturally generalized as
import scala.language.higherKinds
def onLeft[F[+_],A,B](x: => EitherT[F, A, B])
(y: A => EitherT[F, A, B])
(implicit F: Bind[F]): EitherT[F, A, B] =
{
val g = x.run
EitherT(F.bind(g) {
case -\/(l) => y(l).run
case \/-(_) => g
})
}
This is basically the same thing as swapping left/right and then using monadic binding
def onLeft1[F[+_],A,B](x: => EitherT[F, A, B])
(y: A => EitherT[F, A, B])
(implicit F: Monad[F]): EitherT[F, A, B] =
x.swap.flatMap((a: A) => y(a).swap).swap
but of course the first variant is more efficient (and also a bit more general in F).