Can someone help me, how to define this function:
def lift[A, B, T](op: (T,T) => T)(f: A => T, g: B => T): (A,B) => T = /* ... */
Perhaps
def lift[A, B, T](op: (T,T) => T)(f: A => T, g: B => T): (A,B) => T =
(a: A, b: B) => op(f(a), g(b))
which gives
def op(a: Int, b: Int): Int = a + b
def f(x: String): Int = x.toInt
def g(x: List[String]): Int = x.length
lift(op)(f,g)("41", List("2"))
// Int = 42
Related
I have a function g which need parameter (Int, (Int, Int)) => Int, and a flat function f0 (Int, Int, Int) => Int
I want to construct a function ft which can flat parameters of g to f0.
Here is the example:
val f0: ((Int, Int, Int)) => Int = (x: (Int, Int, Int)) => {
x._1 + x._2 + x._3
}
def g(f: ((Int, (Int, Int))) => Int): Int = f(1,(2,3))
def ft(f: ((Int, Int, Int)) => Int): ((Int, (Int, Int))) => Int = (p: (Int, (Int, Int))) => {
f(p._1, p._2._1, p._2._2)
}
// invoke it
g(ft(f0))
But I have several functions of nested tuples, and I don't want to transform each manually. For example, ((Int, Int), (Int, Int)) => Int to (Int, Int, Int, Int) => Int
Here said it could use shapeless
Then the new function would like
import shapeless._
import ops.tuple.FlatMapper
trait LowPriorityFlatten extends Poly1 {
implicit def default[T] = at[T](Tuple1(_))
}
object flatten extends LowPriorityFlatten {
implicit def caseTuple[P <: Product](implicit lfm: Lazy[FlatMapper[P, flatten.type]]) =
at[P](lfm.value(_))
}
def ft(f: ((Int, Int, Int)) => Int): ((Int, (Int, Int))) => Int = (p: (Int, (Int, Int))) => {
val a: (Int, Int, Int) = flatten(p).asInstanceOf[(Int, Int, Int)]
f(a)
}
Code above has two problem:
how to define function ft[A, B, C](f: A => C): B where A is a flatten type of B ?
flatten(p) will product type FlatMapper.this.Out and miss the type, so I use asInstanceOf to cast type here.
So, How to write a function to flatten any kind of nested tuple in a parameter?
The following code works in Scala 3:
scala> type Flat[T <: Tuple] <: Tuple = T match
| case EmptyTuple => EmptyTuple
| case h *: t => h match
| case Tuple => Tuple.Concat[Flat[h], Flat[t]]
| case _ => h *: Flat[t]
|
scala> def flat[T <: Tuple](v: T): Flat[T] = (v match
| case e: EmptyTuple => e
| case h *: ts => h match
| case t: Tuple => flat(t) ++ flat(ts)
| case _ => h *: flat(ts)).asInstanceOf[Flat[T]]
def flat[T <: Tuple](v: T): Flat[T]
scala> def ft[A <: Tuple, C](f: Flat[A] => C): A => C = a => f(flat(a))
def ft[A <: Tuple, C](f: Flat[A] => C): A => C
scala> val f0: ((Int, Int, Int)) => Int = x => x._1 + x._2 + x._3
scala> def g0(f: ((Int, (Int, Int))) => Int): Int = f(1,(2,3))
scala> g0(ft(f0))
val res0: Int = 6
Edit: Add scala2's version:
import shapeless._
import ops.tuple.FlatMapper
import syntax.std.tuple._
trait LowPriorityFlat extends Poly1 {
implicit def default[T] = at[T](Tuple1(_))
}
object Flat extends LowPriorityFlat {
implicit def caseTuple[P <: Product](implicit fm: FlatMapper[P, Flat.type]) =
at[P](_.flatMap(Flat))
}
type F[A, B] = FlatMapper.Aux[A, Flat.type, B]
def flatTup[T <: Product](t: T)(implicit lfm: FlatMapper[T, Flat.type]): lfm.Out =
FlatMapper[T, Flat.type].apply(t)
def flatFun[A <: Product, B <: Product, C](f: B => C)
(implicit lfm: F[A, B]): A => C =
a => f(flatTup(a))
val f0: ((Int, Double, Int, Double)) => Double = { case(i1, d1, i2, d2) => (i1 + i2) / (d1 + d2) }
def g0(f: (((Int, Double), (Int, Double))) => Double): Double = f((1, 2.0), (3, 4.0))
val r0 = g0(flatFun(f0))
The java Predicate interface provides an or method that is used to combine multiple predicates. Example:
Predicate<Integer> p1;
Predicate<Integer> p2;
Predicate<Integer> p2 = p1.or(p2)
Since scala does not have the Predicate interface but uses Function1[A, Boolean] for this purpose what would be the best way to write this? Preferably without the use of external libraries.
I try to avoid the following:
val p1: (A => Boolean)
val p2: (A => Boolean)
val p3: (A => Boolean) = (a => p1(a) || p2(a))
You could provide the Predicate functionality in an implicit value class as
implicit class Predicate[A](val p1: A => Boolean) extends AnyVal {
def or[B >: A](p2: B => Boolean) = (a: A) => p1(a) || p2(a)
}
and then do
val gtOne = (x: Int) => x > 1
val ltMinusOne = (x: Int) => x < -1
val absGtOne = gtOne or ltMinusOne
absGtOne(-2) // true
absGtOne(0) // false
absGtOne(2) // true
You could provide an implicit conversion from A ⇒ Boolean to Predicate which supports the operations you want. Something like this:
implicit class Predicate[A](val p: A ⇒ Boolean) extends AnyVal {
type Predicate[A] = A ⇒ Boolean
def unary_! = (a: A) ⇒ !p(a)
def ==[B >: A](x: Predicate[B]) = (a: A) ⇒ p(a) == x(a)
def !=[B >: A](x: Predicate[B]) = (a: A) ⇒ p(a) != x(a)
def ||[B >: A](x: Predicate[B]) = (a: A) ⇒ p(a) || x(a)
def &&[B >: A](x: Predicate[B]) = (a: A) ⇒ p(a) && x(a)
def ^[B >: A](x: Predicate[B]) = (a: A) ⇒ p(a) ^ x(a)
def |[B >: A](x: Predicate[B]) = (a: A) ⇒ p(a) | x(a)
def &[B >: A](x: Predicate[B]) = (a: A) ⇒ p(a) & x(a)
}
This implements all the methods available in Boolean with the same semantics, e.g. Predicate.&& will only evaluate the second predicate if the first evaluates to true, whereas Predicate.| will always evaluate both predicates.
It's not part of the standard library, but if you only need simple expressions, you could:
Use the Java version, possibly using extension methods for syntactic sugar like p1 || p2 instead of p1.or(p2).
Roll your own case class Predicate[-A](p: A => Boolean) with a few simple methods like:
def ||[B <: A](other: Predicate[B]): Predicate[B] = ???
My stateful predicate:
/**
* Predicate logic with the state to print the function in natural language
*/
object StatefulPredicate {
class Predicate[E, T](predicate: E => T => Boolean, e: E, chain: Option[(Operator, Predicate[E, T])] = None) {
def test(t: T): Boolean = chain.map(c => c._1.execute(t, c._2.test(t), predicate(e))).getOrElse(predicate(e)(t))
def and(e: E): Predicate[E, T] = new Predicate[E, T](this.predicate, e, Some(AND, this))
def or(e: E): Predicate[E, T] = new Predicate[E, T](this.predicate, e, Some(OR, this))
override def toString: String = chain.map(c => c._2.toString + " " + c._1.toString + " " + e.toString).getOrElse(e.toString)
}
sealed trait Operator {
def execute[T](t: T, op1: Boolean, op2: T => Boolean): Boolean
}
case object AND extends Operator {
override def execute[T](t: T, op1: Boolean, op2: T => Boolean): Boolean = op1 && op2(t)
override def toString: String = "and"
}
case object OR extends Operator {
override def execute[T](t: T, op1: Boolean, op2: T => Boolean): Boolean = op1 || op2(t)
override def toString: String = "or"
}
def main(args: Array[String]): Unit = {
val p1: Predicate[Int, Seq[Int]] = new Predicate(e => s => s.contains(e), 10)
val p2: Predicate[Int, Seq[Int]] = p1.or(25)
val p3: Predicate[Int, Seq[Int]] = p2.and(25)
val p4: Predicate[Int, Seq[Int]] = p3.and(40)
print(p4.test(Seq[Int](10, 20, 30, 40)))
}
}
I'm trying to figure out how to abstract over a curried function.
I've can abstract over an uncurried function via:
def liftAU[F, P <: Product, L <: HList, R, A[_]](f: F)
(implicit
fp: FnToProduct.Aux[F, L => R],
gen: Generic.Aux[P, L],
ap: Applicative[A]
): A[P] => A[R] = p => p.map(gen.to).map(f.toProduct)
This will take a function like (Int, Int) => Int and turn it into something like Option[(Int, Int)] => Option[Int]. And it works for any arity of function.
I want to create the curried version which will take a function like Int => Int => Int and convert it to Option[Int] => Option[Int] => Option[Int].
It should also work for any arity of curried function.
Since FnToProduct only works on the first parameter list, it's not helpful here, I've also tried to write some recursive definitions at the typelevel, but I'm having issues defining the types.
Not really sure if its possible, but would love to know if others have tried anything like this.
Dmytro's answer doesn't actually work for me unless I change the instance names in one of the objects, and even then it doesn't work for a function like Int => Int => Int => Int, and I find working with Poly values really annoying, so instead of debugging the previous answer, I'm just going to write my own.
You can actually write this operation pretty nicely using a 100% Shapeless-free type class:
import cats.Applicative
trait LiftCurried[F[_], I, O] {
type Out
def apply(f: F[I => O]): F[I] => Out
}
object LiftCurried extends LowPriorityLiftCurried {
implicit def liftCurried1[F[_]: Applicative, I, I2, O2](implicit
lc: LiftCurried[F, I2, O2]
): Aux[F, I, I2 => O2, F[I2] => lc.Out] = new LiftCurried[F, I, I2 => O2] {
type Out = F[I2] => lc.Out
def apply(f: F[I => I2 => O2]): F[I] => F[I2] => lc.Out =
(Applicative[F].ap(f) _).andThen(lc(_))
}
}
trait LowPriorityLiftCurried {
type Aux[F[_], I, O, Out0] = LiftCurried[F, I, O] { type Out = Out0 }
implicit def liftCurried0[F[_]: Applicative, I, O]: Aux[F, I, O, F[O]] =
new LiftCurried[F, I, O] {
type Out = F[O]
def apply(f: F[I => O]): F[I] => F[O] = Applicative[F].ap(f) _
}
}
It's probably possible to make that a little cleaner but I find it reasonable readable as it is.
You might want to have something concrete like this:
def liftCurriedIntoOption[I, O](f: I => O)(implicit
lc: LiftCurried[Option, I, O]
): Option[I] => lc.Out = lc(Some(f))
And then we can demonstrate that it works with some functions like this:
val f: Int => Int => Int = x => y => x + y
val g: Int => Int => Int => Int = x => y => z => x + y * z
val h: Int => Int => Int => String => String = x => y => z => _ * (x + y * z)
And then:
scala> import cats.instances.option._
import cats.instances.option._
scala> val ff = liftCurriedIntoOption(f)
ff: Option[Int] => (Option[Int] => Option[Int]) = scala.Function1$$Lambda$1744/350671260#73d06630
scala> val gg = liftCurriedIntoOption(g)
gg: Option[Int] => (Option[Int] => (Option[Int] => Option[Int])) = scala.Function1$$Lambda$1744/350671260#2bb9b82c
scala> val hh = liftCurriedIntoOption(h)
hh: Option[Int] => (Option[Int] => (Option[Int] => (Option[String] => Option[String]))) = scala.Function1$$Lambda$1744/350671260#45eec9c6
We can also apply it a couple more times just for the hell of it:
scala> val hhhh = liftCurriedIntoOption(liftCurriedIntoOption(hh))
hhh: Option[Option[Option[Int]]] => (Option[Option[Option[Int]]] => (Option[Option[Option[Int]]] => (Option[Option[Option[String]]] => Option[Option[Option[String]]]))) = scala.Function1$$Lambda$1744/350671260#592593bd
So the types look okay, and for the values…
scala> ff(Some(1))(Some(2))
res0: Option[Int] = Some(3)
scala> ff(Some(1))(None)
res1: Option[Int] = None
scala> hh(Some(1))(None)(None)(None)
res2: Option[String] = None
scala> hh(Some(1))(Some(2))(Some(3))(Some("a"))
res3: Option[String] = Some(aaaaaaa)
…which I think is what you were aiming for.
You can define recursive Poly
object constNone extends Poly1 {
implicit def zeroCase[In]: Case.Aux[In, Option[Int]] = at(_ => None)
implicit def succCase[In, In1, Out](implicit
cse: Case.Aux[In, Out]): Case.Aux[In1, In => Out] = at(_ => cse(_))
}
object transform extends Poly1 {
implicit def zeroCase: Case.Aux[Int, Option[Int]] = at(Some(_))
implicit def succCase[In, Out](implicit
cse: Case.Aux[In, Out],
noneCase: constNone.Case.Aux[In, Out]
): Case.Aux[Int => In, Option[Int] => Out] =
at(f => {
case Some(n) => cse(f(n))
case None => noneCase(f(0))
})
}
(transform((x: Int) => (y: Int) => x + y) _)(Some(1))(Some(2)) //Some(3)
(transform((x: Int) => (y: Int) => x + y) _)(Some(1))(None) //None
(transform((x: Int) => (y: Int) => x + y) _)(None)(Some(2)) //None
I have the following two functions, written in scala:
def f: (Int,Int) => Int = (x,y) => x+y
def g: Int=>Int=>Int=x=>y=>x+y
Now I want to write a function that curries the function f, taking one argument, into a function g, taking two arguments.
Beside the definition I cant find a solution to this problem
curry: ((Int, Int) => Int) => (Int => Int => Int):
Any suggestions?
Can you simply use the curried function?
scala> def f: (Int,Int) => Int = (x,y) => x+y
f: (Int, Int) => Int
scala> val g = f.curried
g: Int => (Int => Int) = <function1>
scala> g(1)(2)
res0: Int = 3
Edit: an example of a curry function based on the source code of curried in Function2:
def curry[A,B,C](f: (A,B) => C): A => B => C = (x1: A) => (x2: B) => f(x1,x2)
scala> def f(x: Int, y: Int) = x + y
f: (x: Int, y: Int)Int
scala> def curry(fn: (Int, Int) => Int) = (x: Int) => (y: Int) => fn(x, y)
curry: (fn: (Int, Int) => Int)Int => (Int => Int)
scala> val g = curry(f)
g: Int => (Int => Int) = <function1>
scala> g(3)(4)
res0: Int = 7
If I have:
val f : A => B => C
This is shorthand for:
val f : Function1[A, Function1[B, C]]
How do I get a function g with the signature:
val g : (A, B) => C = error("todo")
(i.e.)
val g : Function2[A, B, C] //or possibly
val g : Function1[(A, B), C]
in terms of f?
scala> val f : Int => Int => Int = a => b => a + b
f: (Int) => (Int) => Int = <function1>
scala> Function.uncurried(f)
res0: (Int, Int) => Int = <function2>
Extending retonym's answer, for completeness
val f : Int => Int => Int = a => b => a + b
val g: (Int, Int) => Int = Function.uncurried(f)
val h: ((Int, Int)) => Int = Function.tupled(g)
The converse functions for both of these operations are also provided on the Function object, so you could write the above backwards, if you wished
val h: ((Int, Int)) => Int = x =>(x._1 + x._2)
val g: (Int, Int) => Int = Function.untupled(h)
val f : Int => Int => Int = g.curried //Function.curried(g) would also work, but is deprecated. Wierd
Just to round out the answer, although there is a library method to do this, it may also be instructive to do it by hand:
scala> val f = (i: Int) => ((s: String) => i*s.length)
f: (Int) => (String) => Int = <function1>
scala> val g = (i: Int, s: String) => f(i)(s)
g: (Int, String) => Int = <function2>
Or in general,
def uncurry[A,B,C](f: A=>B=>C): (A,B)=>C = {
(a: A, b: B) => f(a)(b)
}
Similar to the answer by Rex Kerr but easier to read.
type A = String
type B = Int
type C = Boolean
val f: A => B => C = s => i => s.toInt+i > 10
val f1: (A, B) => C = f(_)(_)