How to write an implicit Numeric for a tuple - scala

I have a scenario where I would like to call sum on a sequence of (Double, Double) tuples.
Ideally I would like to do something like the following:
implicit def toTupleNumeric[T](num: Numeric[T]) = new Numeric[(T, T)] {
def plus(x: (T, T), y: (T, T)): (T, T) = (num.plus(x._1, y._1), num.plus(x._2, y._2))
def minus(x: (T, T), y: (T, T)): (T, T) = (num.minus(x._1, y._1), num.minus(x._2, y._2))
def times(x: (T, T), y: (T, T)): (T, T) = (num.times(x._1, y._1), num.times(x._2, y._2))
def negate(x: (T, T)): (T, T) = (num.negate(x._1), num.negate(x._2))
def fromInt(x: Int): (T, T) = (num.fromInt(x), num.fromInt(x))
def toInt(x: (T, T)): Int = num.toInt(x._1) + num.toInt(x._2)
def toLong(x: (T, T)): Long = num.toLong(x._1) + num.toLong(x._2)
def toFloat(x: (T, T)): Float = num.toFloat(x._1) + num.toFloat(x._2)
def toDouble(x: (T, T)): Double = num.toDouble(x._1) + num.toDouble(x._2)
def compare(x: (T, T), y: (T, T)): Int = num.compare(x._1, y._1) match {
case c if c == 0 => num.compare(x._2, y._2)
case c => c
}
}
But when I call sum:
val seq: Seq[(Double, Double)] = ...
val sum = seq.sum
I get a compiler error:
could not find implicit value for parameter num: Numeric[(Double,
Double)]
Is there a way to implement such an implicit?

You seem to confuse conditional implicit
implicit def toTupleNumeric[T](implicit num: Numeric[T]): Numeric[(T, T)] = ...
with implicit conversion
implicit def toTupleNumeric[T](num: Numeric[T]): Numeric[(T, T)] = ...
With the former you're specifying that the data type (T, T) (aka scala.Tuple2[T, T]) is an instance of the type class Numeric provided that T is an instance of the type class. This means that if there is an implicit of the type Numeric[T] then there is an implicit of the type Numeric[(T, T)]. In Scala 3 the type of this conditional implicit is Numeric[T] ?=> Numeric[(T, T)] (aka ContextFunction1[Numeric[T], Numeric[(T, T)]]).
With the latter you're specifying that the data type Numeric[T] can be used where the data type Numeric[(T, T)] is expected and this function Numeric[T] => Numeric[(T, T)] (aka Function1[Numeric[T], Numeric[(T, T)]]) should be used for such transformation automatically.
I guess you meant the former. So add implicit to the parameter (num: Numeric[T]) making it an implicit parameter (implicit num: Numeric[T]). Your code will compile then.
You can refresh your understanding implicits in Scala:
Understanding implicit in Scala
What are type classes in Scala useful for?
Implicit conversion vs. type class
How can I chain implicits in Scala?
Why are implicit conversion deprecated in scala?
Can someone explain me implicit conversions in Scala?
Scala - Implicit conversion to implicit argument
Implicit conversion with implicit parameter
https://docs.scala-lang.org/tour/implicit-parameters.html https://docs.scala-lang.org/tour/implicit-conversions.html
https://docs.scala-lang.org/scala3/book/ca-contextual-abstractions-intro.html ...
https://docs.scala-lang.org/scala3/reference/contextual/index.html ...
You can also rewrite your definition using a context bound (: Numeric), importing implicits, extension methods aka type-class syntax (.toInt, .+(...)), and type-class materializer (Numeric.apply[T])
import Numeric.Implicits._
implicit def toTupleNumeric[T: Numeric]: Numeric[(T, T)] =
new Numeric[(T, T)] {
override def plus(x: (T, T), y: (T, T)): (T, T) = (x._1 + y._1, x._2 + y._2)
override def minus(x: (T, T), y: (T, T)): (T, T) = (x._1 - y._1, x._2 - y._2)
override def times(x: (T, T), y: (T, T)): (T, T) = (x._1 * y._1, x._2 * y._2)
override def negate(x: (T, T)): (T, T) = (-x._1, -x._2)
override def fromInt(x: Int): (T, T) = (Numeric[T].fromInt(x), Numeric[T].fromInt(x))
override def toInt(x: (T, T)): Int = x._1.toInt + x._2.toInt
override def toLong(x: (T, T)): Long = x._1.toLong + x._2.toLong
override def toFloat(x: (T, T)): Float = x._1.toFloat + x._2.toFloat
override def toDouble(x: (T, T)): Double = x._1.toDouble + x._2.toDouble
override def compare(x: (T, T), y: (T, T)): Int = Numeric[T].compare(x._1, y._1) match {
case c if c == 0 => Numeric[T].compare(x._2, y._2)
case c => c
}
override def parseString(str: String): Option[(T, T)] = ???
}
What is a "context bound" in Scala?

Related

How to flat nest tuple parameter in function?

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))

HList foldLeft with tuple as zero

I'm trying to foldLeft on a HList with an accumulator of type (HL, Int), where HL is a HList. The program below does not compile. However, if I switch to a simpler accumulator of type HL (by just switching the commented lines with the ones above), it compiles and it works.
Wrapping an HList in a tuple breaks the implicit resolution for the leftFolder. What am I missing?
package foo.bar
import shapeless.{:+:, ::, CNil, Coproduct, Generic, HList, HNil, Lazy, Poly2}
import shapeless.ops.hlist.{LeftFolder, Reverse}
object StackOverflow extends App {
trait MyTypeclass[T] {
def doSomething(t: T): (T, Int)
}
implicit lazy val stringInstance: MyTypeclass[String] = (t: String) => (t, 0)
implicit val hnilInstance: MyTypeclass[HNil] = (t: HNil) => (t, 0)
implicit def hlistInstance[H, T <: HList](
implicit
head: Lazy[MyTypeclass[H]],
tail: MyTypeclass[T]
): MyTypeclass[H :: T] =
(ht: H :: T) =>
ht match {
case h :: t =>
val (hres, hint) = head.value.doSomething(h)
val (tres, tint) = tail.doSomething(t)
(hres :: tres, hint + tint)
}
implicit val cnilInstance: MyTypeclass[CNil] = (t: CNil) => ???
implicit def coproductInstance[L, R <: Coproduct](
implicit
head: Lazy[MyTypeclass[L]],
tail: MyTypeclass[R]
): MyTypeclass[L :+: R] = (lr: L :+: R) => ???
object leftFolder extends Poly2 {
implicit def caseAtSimple[F, HL <: HList]: Case.Aux[HL, F, F :: HL] =
at {
case (acc, f) => f :: acc
}
implicit def caseAtComplex[F, HL <: HList]: Case.Aux[(HL, Int), F, (F :: HL, Int)] =
at {
case ((acc, i), f) => (f :: acc, i)
}
}
implicit def genericInstance[T, HL <: HList, LL <: HList](
implicit
gen: Generic.Aux[T, HL],
myTypeclass: Lazy[MyTypeclass[HL]],
// folder: LeftFolder.Aux[HL, HNil, leftFolder.type, LL],
folder: LeftFolder.Aux[HL, (HNil, Int), leftFolder.type, (LL, Int)],
reverse: Reverse.Aux[LL, HL]
): MyTypeclass[T] = (t: T) => {
val generic = gen.to(t)
val (transformed, idx) = myTypeclass.value.doSomething(generic)
// val ll = transformed.foldLeft(HNil: HNil)(leftFolder)
val (ll, _) = transformed.foldLeft((HNil: HNil, 0))(leftFolder)
val reversed = reverse(ll)
(gen.from(reversed), idx)
}
def doSomething[T](t: T)(implicit myTypeclass: MyTypeclass[T]): T = myTypeclass.doSomething(t)._1
case class Foo(
str1: String,
str2: String
)
val original = Foo("Hello World!", "Hello there!")
val result = doSomething(original)
println(result == original)
}
You want implicits to do too much work in a single step.
Try to add one more type parameter Out
implicit def genericInstance[T, HL <: HList, Out, LL <: HList](
implicit
gen: Generic.Aux[T, HL],
myTypeclass: Lazy[MyTypeclass[HL]],
//folder: LeftFolder.Aux[HL, (HNil, Int), leftFolder.type, (LL, Int)],
folder: LeftFolder.Aux[HL, (HNil, Int), leftFolder.type, Out],
ev: Out <:< (LL, Int), // added
reverse: Reverse.Aux[LL, HL]
): MyTypeclass[T] = (t: T) => {
val generic = gen.to(t)
val (transformed, idx) = myTypeclass.value.doSomething(generic)
//val (ll, _) = transformed.foldLeft((HNil: HNil, 0))(leftFolder)
val (ll, _) = ev(transformed.foldLeft((HNil: HNil, 0))(leftFolder))
val reversed = reverse(ll)
(gen.from(reversed), idx)
}
Read about over-constrained implicits:
https://books.underscore.io/shapeless-guide/shapeless-guide.html#sec:type-level-programming:chaining (4.3 Chaining dependent functions)
Scala shapeless Generic.Aux implicit parameter not found in unapply
Extract FieldType key and value from HList
How to implicitly figure out the type at the head of a shapeless HList
How to infer inner type of Shapeless record value with unary type constructor?

Scala predicate composition

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)))
}
}

Tagless final example in Scala requires superfluous second interp arg

I'm playing around with implementing a tagless final DSL & interpreter in Scala, based on this blog post written in Haskell.
I can get an example running - see code below, but I don't quite understand why I need testVal(Interp)(Interp). If I only supply a single Interp argument, then I get the following compile errors:
Error:(29, 24) could not find implicit value for evidence parameter of type Test.Expr[Test.Id]
val x = testVal(Interp)
Error:(29, 24) not enough arguments for method testVal: (implicit evidence$1: Test.Expr[Test.Id])Test.Id[Int].
Unspecified value parameter evidence$1.
val x = testVal(Interp)
Is there a simple way to eliminate one of the Interp arguments?
object Test {
trait Expr[F[_]] {
def const(i: Int): F[Int]
def lam[A, B](f: F[A] => F[B]): F[A => B]
def app[A, B](f: F[A => B], a: F[A]): F[B]
def add(x: F[Int], y: F[Int]): F[Int]
}
type Id[A] = A
object Interp extends Expr[Id] {
override def const(i: Int): Id[Int] = i
override def lam[A, B](f: Id[A] => Id[B]): Id[A => B] = f
override def app[A, B](f: Id[A => B], a: Id[A]): Id[B] = f(a)
override def add(x: Id[Int], y: Id[Int]): Id[Int] = x + y
}
def testVal[F[_]: Expr](f: Expr[F]): F[Int] =
f.app(
f.lam[Int, Int](
x => f.add(x, f.const(1))),
f.const(10)
)
def main(args: Array[String]): Unit = {
// val x = testVal(Interp) -- won't compile
val x = testVal(Interp)(Interp)
println(x)
}
}
The syntax
def f[X: Y](args: Types): Res = { ... }
is a shortcut for
def f[X](args: Types)(implicit yx: Y[X]): Res = { ... }
so if you write
def testVal[F[_]: Expr](f: Expr[F]): F[Int] = { ... }
then it's the same as if you wrote
def testVal[F[_]](f: Expr[F])(implicit redundant: Expr[F]): F[Int] = { ... }
but you obviously don't need the same Expr[F] twice.
The signature should be either
def testVal[F[_]: Expr]: F[Int]
or
def testVal[F[_]](implicit f: Expr[F]): F[Int]
but not both at the same time.
Here is a full example, which also shows how to get the f using implicitly in the case that you decide to use the F: Expr variant (which does not assign a name to the implicit argument):
import scala.language.higherKinds
object Test {
trait Expr[F[_]] {
def const(i: Int): F[Int]
def lam[A, B](f: F[A] => F[B]): F[A => B]
def app[A, B](f: F[A => B], a: F[A]): F[B]
def add(x: F[Int], y: F[Int]): F[Int]
}
type Id[A] = A
object Interp extends Expr[Id] {
override def const(i: Int): Id[Int] = i
override def lam[A, B](f: Id[A] => Id[B]): Id[A => B] = f
override def app[A, B](f: Id[A => B], a: Id[A]): Id[B] = f(a)
override def add(x: Id[Int], y: Id[Int]): Id[Int] = x + y
}
def testVal[F[_]: Expr]: F[Int] = {
implicit val f = implicitly[Expr[F]]
f.app(
f.lam[Int, Int](
x => f.add(x, f.const(1))),
f.const(10)
)
}
def main(args: Array[String]): Unit = {
val x = testVal(Interp)
println(x)
}
}
Moreover, if you make Interp itself implicit, then you can omit all argument lists when invoking testVal, and instead write just
val x = testVal // no arguments at all.

Implicit conversion is not applied if a method has type parameter

The question is based on the discussion here. This is the setup:
implicit def CToC2(obj: C1): C2 = {
new C2()
}
class C1() {
def f[U](f: (Int, Int) => U): U = f(1, 1)
}
class C2() {
def f[U](f: ((Int, Int)) => U): U = f(2, 2)
}
I'd expect that trying to call the function with a signature that exists in C2, scala would use the implicit conversion to satisfy the call:
val c1 = new C1()
val ff: ((Int, Int)) => Unit = t => println(t._1 + t._2)
But this fails:
scala> c1.f(ff)
Error:(16, 7) type mismatch;
found : ((Int, Int)) => Unit
required: (Int, Int) => ?
Interestingly if I drop the type parameter from C1, it works fine:
class C1() {
def f(f: (Int, Int) => Unit): Unit = f(1, 1)
}