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))
Related
I'm new to Scala, so the answer might be obvious.
When going through FP in Scala FP in Scala I noticed that the unit method is placed on the companion object, but not the class, so I tried moving it to the class.
It resulted in an error which I don't understand, can someone explain it to me?
When you uncomment the unit method on the class and comment it out on the companion object it results in this error:
Why is that?
import State._
case class State[S, A](run: S => (A, S)) {
def map[B](f: A => B): State[S, B] =
flatMap(a => unit(f(a)))
def map2[B, C](sb: State[S, B])(f: (A, B) => C): State[S, C] =
flatMap(a => sb.map(b => f(a, b)))
def flatMap[B](f: A => State[S, B]): State[S, B] = State(s => {
val (a, s1) = run(s)
f(a).run(s1)
})
// This results in an error here:
// flatMap(a => unit(f(a))) ... Required A, found B
// def unit(a: A): State[S, A] = State(s => (a, s)) // ERROR
}
object State {
// Comment out when uncommenting above
def unit[S, A](a: A): State[S, A] = State(s => (a, s))
}
The error explains the problem, but here is the breakdown.
Start with map:
def map[B](f: A => B): State[S, B] =
flatMap(a => unit(f(a)))
Since f returns an unknown type B, this is calling unit with a value of type B. But unit is defined to take A, which is a type parameter of the case class:
def unit(a: A): State[S, A] = State(s => (a, s))
Since B might not be A, the compiler complains.
The code inside the companion object is different:
object State {
def unit[T, U](a: U): State[T, U] = State(s => (a, s))
}
I have re-named the type parameters to make it clear that they are now unrelated to the type parameters of the case class. And since the argument type of unit can be any type U it is OK to pass a value of type B to it.
To fix the definition of unit inside the case class, give it a type parameter:
case class State[S, A](run: S => (A, S)) {
// ...
def unit[T](a: T): State[S, T] = State(s => (a, s))
}
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 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
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)
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.