class P(name: String)
class E(_name: String, role: String) extends P(_name)
def testF[T <: P](x: List[T]): List[T] = x
val le = List(new E("Henry", "Boss"))
class Test[R <: E](l: List[R]) {
def r[O <: P] (): List[O] = testF(l)
}
I get:
Error:(8, 38) type mismatch;
found : List[R]
required: List[O]
def r[O <: P] (): List[O] = testF(l)
My intuition suggests that this should have worked because T has a tighter upper type bound than O.
**** EDIT ****
def findNN[A, B <: A, C <: A, T] (seq: Seq[B], n: Int, center: C, distance: (A, A) => T)
(implicit ord: Ordering[T]): Seq[B] = {
import ord._
val ds = seq map ( (a: A) => distance(a, center))
val uds = ds.distinct
//#TODO: replace quickSelect with median-of algorithm if necessary
val kel = quickSelect(uds, n)
val z = seq zip ds
val (left, _) = z partition Function.tupled((_, d: T) => d <= kel)
left map {t => t._1}
}
OK, let's have a look at the example above.
The superclass A provides the method distance.
I would like to use the function findNN on a seq[B] having a center in a class C. distance should work because it works on A
Based on feedback provided, there's no way to simplify the type signatures above.
You made misprinting, you need >: rather then :<
class P(name: String)
class E(_name: String, role: String) extends P(_name)
def testF[T >: P](): List[T] = List(new P("Henry"))
You are trying to limit the type of the result using a type parameter R (with an upper bound type E), while you are not using the type R in your function.
An example of a correct use of a type parameter (with an upper bound):
def testF[T <: P](list: List[T]): List[T] = list
testF(List(new P("Tom")))
// List[P] = List(P#43bc21f0)
testF(List(new E("Jerry", "Mouse")))
// List[E] = List(E#341c1e65)
An incorrect use of a type parameter:
// does not compile, what is A ??
def foo[A]: List[A] = List("bar")
Related
I am aware that in Scala 3 it is now possible to convert between case class instances and tuples using Tuple.fromProductTyped and summon[Mirror.Of].fromProduct.
I would like to be able to define a typeclass that witnesses that a case class T can be converted to and from (A, B) using the aforementioned methods.
I've defined the typeclass like so:
trait IsPair[T, A, B]:
def toTuple(t: T): (A, B)
def fromTuple(ab: (A, B)): T
How can we derive IsPair for any conforming case class?
With the derivation in place, the following should compile and run without error:
case class Foo(a: Int, b: String)
val fooIsPair = summon[IsPair[Foo, Int, String]]
val foo = Foo(42, "qwerty")
val tuple = (42, "qwerty")
assert(fooIsPair.toTuple(foo) == tuple)
assert(fooIsPair.fromTuple(tuple) == foo)
You can just use a Mirror but restrict it to be for pair-like case classes:
import scala.deriving.Mirror
sealed trait IsPair[T]:
type A
type B
def toTuple(t: T): (A, B)
def fromTuple(ab: (A, B)): T
object IsPair:
type Aux[T, X, Y] = IsPair[T] { type A = X; type B = Y }
inline def apply[T](using ev: IsPair[T]): ev.type = ev
given instance[T <: Product, X, Y](using
ev: Mirror.Product { type MirroredType = T; type MirroredMonoType = T; type MirroredElemTypes = (X, Y) }
): IsPair[T] with
override final type A = X
override final type B = Y
override def toTuple(t: T): (X, Y) =
Tuple.fromProductTyped(t)
override def fromTuple(xy: (X, Y)): T =
ev.fromProduct(xy)
end IsPair
That way we can do this:
val foo = Foo(42, "qwerty")
val tuple = (42, "qwerty")
val fooIsPair = IsPair[Foo]
assert(fooIsPair.toTuple(foo) == tuple)
assert(fooIsPair.fromTuple(tuple) == foo)
You can see the code running here.
I have a type X[D <: Int] that I would like to convert to implicitly from a tuple.
Specifically a tuple of length D whose members are all Int should be convertable to an X[D].
I am not able to write a Conversion[A, B] to properly perform this.
Scastie playground with my attempt
https://scastie.scala-lang.org/R3BEymtWSaqTCtDTsirTKw
import scala.language.implicitConversions
// tuple types
type TupleAllAre[A] = [T <: Tuple] =>> T =:= TupleElementsAre[T, A]
type TupleElementsAre[T <: Tuple, A] <: Tuple = T match
case A *: rest => A *: TupleElementsAre[rest, A]
case EmptyTuple => EmptyTuple
// tuple types work
val s1 = summon[TupleAllAre[Int][(Int, Int)]]
// Expected error
// val s2 = summon[TupleAllAre[Int][(Int, String, Int)]]
// target classes / methods
class X[D <: Int](x: Seq[Int]):
def size: Int = x.size
def definition[D <: Int](x: X[D]): Unit = ???
def def_with_conversion[T <: Tuple: TupleAllAre[Int]] (tuple: T) (using c: Conversion[T, X[Tuple.Size[T]]]): X[Tuple.Size[T]] = c(tuple)
class M[D <: Int]:
def apply(x: X[D]): Unit = ???
val m1 = M[2]()
extension [T <: Tuple: TupleAllAre[Int]] (tuple: T)
def ext(using c: Conversion[T, X[Tuple.Size[T]]]): X[Tuple.Size[T]] = c(tuple)
// conversion
given [T <: Tuple: TupleAllAre[Int]]: Conversion[T, X[Tuple.Size[T]]] = ???
// works with a non generic conversion
// given Conversion[(Int, Int), X[2]] = ???
// should all work
val x1: X[2] = (16, 16)
val d1 = definition[2](2, 2)
val d2: X[2] = def_with_conversion(2, 2)
val a1 = m1(2, 2)
val e1: X[2] = (2, 2).ext
If what you are trying to achieve is to have a type that X[D] that represent a tuple of D elements all Integer this is a way to achieve it:
import scala.compiletime.ops.int.*
type S = Singleton & Int
type X[D <: S] = D match
case 0 => EmptyTuple
case _ => Int *: X[-[D, 1]]
val x: X[2] = (1,2)
def definition[D <: S](x: X[D]): Unit = ()
val x1: X[2] = (16, 16)
println(x1)
val d1 = definition[2]((2, 2))
https://scastie.scala-lang.org/alfonsorr/pk2Avg4YToKaWtKUKxinJA
I'm trying to see if there is a way to find a type W2 that is the super type of 2 types W and E.
In my solution E represents errors, and W represents Warnings.
What I'm trying to accomplish is a method or that if this fails runs that and moves the error to the warning type.
Here is a simplified example of what I'm doing.
sealed trait Validator[-I, +E, +W, +A] extends Product with Serializable
this type has several cases, which aren't really important here, so instead I'll go over an example usage:
case class MyObj(coords: GeoCoords)
case class GeoCoords(lat: String, long: String)
// Getters
val getLatitude: Validator[GeoCoords, Nothing, Nothing, String] = from[GeoCoords].map(_.lat)
val getLongitude: Validator[GeoCoords, Nothing, Nothing, String] = from[GeoCoords].map(_.long)
val parseLatitude: Validator[GeoCoords, Exception, Nothing, Double] = getLatitude andThen nonEmptyString andThen convertToDouble
val parseLongitude: Validator[GeoCoords, Exception, Nothing, Double] = getLongitude andThen convertToDouble
Now this is a bad example, but what I'm looking to do is that because parseLatitude has an error type of Exception, perhaps I want to give a default instead, but still understand that it failed. I'd like to move the Exception from the E error param to the W warning param like this:
val defaultLatitude: Validator[GeoCoords, Nothing, Nothing, Double] = success(0)
val finalLatitude: Validator[GeoCoords, Nothing, Exception, Double] = parseLatitude or defaultLatitude
But as well, if instead of supplying default, the other action I take after the or may fail as well, therefore this should also be the case:
val otherAction: Validator[GeoCoords, Throwable, Nothing, Double] = ???
val finalLatitude: Validator[GeoCoords, Throwable, Exception, Double] = parseLatitude or otherAction
I've tried implementing or in several ways on the Validator type but everytime it gives me an issue, basically casting things all the way up to Any.
def or[I2 <: I, E2 >: E, W2 >: W, B >: A](that: Validator[I2, E2, W2, B]): Validator[I2, E2, W2, B] = Validator.conversion { (i: I2) =>
val aVal: Validator[Any, E, W, A] = this.run(i)
val bVal: Validator[Any, E2, W2, B] = that.run(i)
val a: Vector[W2] = aVal.warnings ++ bVal.warnings
// PROBLEM HERE
val b: Vector[Any] = a ++ aVal.errors
Result(
aVal.warnings ++ aVal.errors ++ bVal.warnings,
bVal.value.toRight(bVal.errors)
)
}
I need to be able to say that W2 is both a supertype of W and of E so that I can concatenate the Vectors together and get type W2 at the end.
A super simplified self contained example is:
case class Example[+A, +B](a: List[A], b: List[B]) {
def or[A2 >: A, B2 >: B](that: Example[A2, B2]): Example[A2, Any] = {
Example(that.a, this.a ++ this.b ++ that.a)
}
}
object stackoverflow extends App {
val example1 = Example(List(1, 2), List(3, 4))
val example2 = Example(List(5, 6), List(7, 8))
val example3 = example1 or example2
}
Where I want the output type of or to be Example[A2, B2] instead of Example[A2, Any]
Actually you want the concatenation of a List[A] and a List[B] to produce a List[A | B], where A | B is union type.
How to define "type disjunction" (union types)?
In Scala 2 union types are absent but we can emulate them with type classes.
So regarding "super simplified example" try a type class LUB (least upper bound)
case class Example[A, B](a: List[A], b: List[B]) {
def or[A2 >: A, B2, AB](that: Example[A2, B2])(
implicit
lub: LUB.Aux[A, B, AB],
lub1: LUB[AB, A2]
): Example[A2, lub1.Out] = {
Example(that.a, (this.a.map(lub.coerce1) ++ this.b.map(lub.coerce2)).map(lub1.coerce1(_)) ++ that.a.map(lub1.coerce2(_)))
}
}
val example1: Example[Int, Int] = Example(List(1, 2), List(3, 4))
val example2: Example[Int, Int] = Example(List(5, 6), List(7, 8))
val example3 = example1 or example2
// example3: Example[Int, Any] // doesn't compile
example3: Example[Int, Int] // compiles
trait LUB[A, B] {
type Out
def coerce1(a: A): Out
def coerce2(b: B): Out
}
trait LowPriorityLUB {
type Aux[A, B, Out0] = LUB[A, B] { type Out = Out0 }
def instance[A, B, Out0](f: (A => Out0, B => Out0)): Aux[A, B, Out0] = new LUB[A, B] {
override type Out = Out0
override def coerce1(a: A): Out0 = f._1(a)
override def coerce2(b: B): Out0 = f._2(b)
}
implicit def bSubtypeA[A, B <: A]: Aux[A, B, A] = instance(identity, identity)
}
object LUB extends LowPriorityLUB {
implicit def aSubtypeB[A <: B, B]: Aux[A, B, B] = instance(identity, identity)
implicit def default[A, B](implicit ev: A <:!< B, ev1: B <:!< A): Aux[A, B, Any] =
instance(identity, identity)
}
// Testing:
implicitly[LUB.Aux[Int, AnyVal, AnyVal]]
implicitly[LUB.Aux[AnyVal, Int, AnyVal]]
implicitly[LUB.Aux[Int, String, Any]]
implicitly[LUB.Aux[Int, Int, Int]]
// implicitly[LUB.Aux[Int, AnyVal, Any]] // doesn't compile
<:!< is from here:
Scala: Enforcing A is not a subtype of B
https://github.com/milessabin/shapeless/blob/master/core/src/main/scala/shapeless/package.scala#L48-L52
If you want Example to be covariant
case class Example[+A, +B]...
make LUB and LUB.Aux contravariant
trait LUB[-A, -B]...
type Aux[-A, -B, Out0] = LUB[A, B] { type Out = Out0 }
Type Driven Development with Idris presents the following generic adder approach:
AdderType : (numArgs : Nat) -> Type
AdderType Z = Int
AdderType (S k) = (next : Int) -> AdderType k
adder : (n : Nat) -> (acc : Int) -> AdderType n
adder Z acc = acc
adder (S k) acc = \x => (adder k (x+acc))
Example:
-- expects 3 Int's to add, with a starting value of 0
*Work> :t (adder 3 0)
adder 3 0 : Int -> Int -> Int -> Int
-- 0 (initial) + 3 + 3 + 3 == 9
*Work> (adder 3 0) 3 3 3
9 : Int
I'm guessing that shapeless can handle the above generic adder function.
How can it be written in Scala with or without shapeless?
Update: I'll leave my original implementation below, but here's one that's a little more direct:
import shapeless._
trait AdderType[N <: Nat] extends DepFn1[Int]
object AdderType {
type Aux[N <: Nat, Out0] = AdderType[N] { type Out = Out0 }
def apply[N <: Nat](base: Int)(implicit at: AdderType[N]): at.Out = at(base)
implicit val adderTypeZero: Aux[Nat._0, Int] = new AdderType[Nat._0] {
type Out = Int
def apply(x: Int): Int = x
}
implicit def adderTypeSucc[N <: Nat](implicit
atN: AdderType[N]
): Aux[Succ[N], Int => atN.Out] = new AdderType[Succ[N]] {
type Out = Int => atN.Out
def apply(x: Int): Int => atN.Out = i => atN(x + i)
}
}
And then:
scala> val at3 = AdderType[Nat._3](0)
at3: Int => (Int => (Int => Int)) = <function1>
scala> at3(3)(3)(3)
res8: Int = 9
Original answer below.
Here's an off-the-cuff Scala translation:
import shapeless._
trait AdderType[N <: Nat] extends DepFn1[Int] {
protected def plus(x: Int): AdderType.Aux[N, Out]
}
object AdderType {
type Aux[N <: Nat, Out0] = AdderType[N] { type Out = Out0 }
def apply[N <: Nat](base: Int)(implicit at: AdderType[N]): Aux[N, at.Out] =
at.plus(base)
private[this] case class AdderTypeZero(acc: Int) extends AdderType[Nat._1] {
type Out = Int
def apply(x: Int): Int = acc + x
protected def plus(x: Int): Aux[Nat._1, Int] = copy(acc = acc + x)
}
private[this] case class AdderTypeSucc[N <: Nat, Out0](
atN: Aux[N, Out0],
acc: Int
) extends AdderType[Succ[N]] {
type Out = Aux[N, Out0]
def apply(x: Int): Aux[N, Out0] = atN.plus(acc + x)
protected def plus(x: Int): Aux[Succ[N], Aux[N, Out0]] = copy(acc = acc + x)
}
implicit val adderTypeZero: Aux[Nat._1, Int] = AdderTypeZero(0)
implicit def adderTypeSucc[N <: Nat](implicit
atN: AdderType[N]
): Aux[Succ[N], Aux[N, atN.Out]] = AdderTypeSucc(atN, 0)
}
And then:
scala> val at3 = AdderType[Nat._3](0)
at3: AdderType[shapeless.Succ[shapeless.Succ[shapeless.Succ[shapeless._0]]]] { ...
scala> at3(3)(3)(3)
res0: Int = 9
It's more verbose and the representation is a little different to get the Scala syntax to work out—our "base case" is essentially an Int => Int instead of an Int because otherwise I don't see a way to avoid needing to write apply or () everywhere—but the basic ideas are exactly the same.
In case you're on a long trip and don't have your shapeless on hands, here is how you can do this in pure Scala. It can be useful for those who are not familiar with shapeless and those who don't use it for some reason.
First of all, we'll need some way to iterate on types, i.e. represent natural numbers in types. You can use any nested type or just define a new one with some aliases for numbers:
sealed trait Nat
trait Zero extends Nat
trait Succ[N <: Nat] extends Nat
// enough for examples:
type _0 = Zero
type _1 = Succ[_0]
type _2 = Succ[_1]
type _3 = Succ[_2]
type _4 = Succ[_3]
// etc...
Of course, if you will often use types like _42 and _342923, it would be more convenient to take an existing Nat type with some macro-magic for constructing those from values, but for our examples it's enough.
Now, the AdderType dependent function type is quite straight forward:
// first we define the type which take a Nat type argument
trait AdderType[N <: Nat] {
type Out
def apply(i: Int): Out
}
// then we inductively construct its values using implicits
case object AdderType {
// base case: N = _0
implicit def zero:
AdderType[_0] { type Out = Int } =
new AdderType[_0] {
type Out = Int
def apply(i: Int): Out = i
}
// induction step: N -> Succ[N]
implicit def succ[N <: Nat, NOut](
implicit prev: AdderType[N] { type Out = NOut }
): AdderType[Succ[N]] { type Out = Int => NOut } =
new AdderType[Succ[N]] {
type Out = Int => NOut
def apply(i: Int): Out = k => prev(i + k)
}
}
Now, to construct an instance of AdderType and apply it, we write a function, which takes a N <: Nat as a type argument and implicitly constructs AdderType[N]:
def adder[N <: Nat](initial: Int)(
implicit adderFunction: AdderType[N]
): adderFunction.Out = adderFunction(initial)
That's it:
scala> val add3Numbers = adder_[_3](0)
add3Numbers: Int => (Int => (Int => Int)) = <function1>
scala> add3Numbers(1)(2)(3)
res0: Int = 6
You can see that the pure solution is not much bigger or more complicated than the one using shapeless (although the latter provides us ready-to-use Nat and DepFn types).
A little addition: if (in some more general case) you don't want to use adderFunction.Out, which sometimes leads to problems, I also have a solution without it. In this particular case it's not any better, but I'll show it anyway.
The key point is to add another type parameter for the out type: adder[N <: Nat, NOut], but then can't pass N as a type to adder, because we will need to write NOut, which want to be inferred (otherwise, what's the point). So we can pass an additional value argument, which will help to derive N type:
def adder[N <: Nat, NOut](n: NatVal[N])(initial: Int)(
implicit adderFunction: AdderType[N] { type Out = NOut }
): NOut = adderFunction(initial)
To construct NatVal[N] we don't need to create an instance of each Nat type, we can use a little trick:
// constructing "values" to derive its type arg
case class NatVal[N <: Nat]()
// just a convenience function
def nat[N <: Nat]: NatVal[N] = NatVal[N]()
Now here is how you use it:
scala> val add3Numbers = adder(nat[_3])(0)
add3Numbers: this.Out = <function1>
scala> add3Numbers(1)(2)(3)
res1: this.Out = 6
You can see that it works, but doesn't show us the actual types. Nevertheless, this approach can work better in cases when you have several implicits that depend others' type members. I mean
def foo[AOut]()(implicit
a: A { type Out = AOut},
b: B { type In = AOut }
) ...
instead of
def foo()(implicit
a: A,
b: B { type In = a.Out }
) ...
Because you cannot reffer to a.Out in the same argument list.
You can find full code in my repo on Github.
I would like to map the elements of a Scala tuple (or triple, ...) using a single function returning type R. The result should be a tuple (or triple, ...) with elements of type R.
OK, if the elements of the tuple are from the same type, the mapping is not a problem:
scala> implicit def t2mapper[A](t: (A,A)) = new { def map[R](f: A => R) = (f(t._1),f(t._2)) }
t2mapper: [A](t: (A, A))java.lang.Object{def map[R](f: (A) => R): (R, R)}
scala> (1,2) map (_ + 1)
res0: (Int, Int) = (2,3)
But is it also possible to make this solution generic, i.e. to map tuples that contain elements of different types in the same manner?
Example:
class Super(i: Int)
object Sub1 extends Super(1)
object Sub2 extends Super(2)
(Sub1, Sub2) map (_.i)
should return
(1,2): (Int, Int)
But I could not find a solution so that the mapping function determines the super type of Sub1 and Sub2. I tried to use type boundaries, but my idea failed:
scala> implicit def t2mapper[A,B](t: (A,B)) = new { def map[X >: A, X >: B, R](f: X => R) = (f(t._1),f(t._2)) }
<console>:8: error: X is already defined as type X
implicit def t2mapper[A,B](t: (A,B)) = new { def map[X >: A, X >: B, R](f: X => R) = (f(t._1),f(t._2)) }
^
<console>:8: error: type mismatch;
found : A
required: X
Note: implicit method t2mapper is not applicable here because it comes after the application point and it lacks an explicit result type
implicit def t2mapper[A,B](t: (A,B)) = new { def map[X >: A, X >: B, R](f: X => R) = (f(t._1),f(t._2)) }
Here X >: B seems to override X >: A. Does Scala not support type boundaries regarding multiple types? If yes, why not?
I think this is what you're looking for:
implicit def t2mapper[X, A <: X, B <: X](t: (A,B)) = new {
def map[R](f: X => R) = (f(t._1), f(t._2))
}
scala> (Sub1, Sub2) map (_.i)
res6: (Int, Int) = (1,2)
A more "functional" way to do this would be with 2 separate functions:
implicit def t2mapper[A, B](t: (A, B)) = new {
def map[R](f: A => R, g: B => R) = (f(t._1), g(t._2))
}
scala> (1, "hello") map (_ + 1, _.length)
res1: (Int, Int) = (2,5)
I’m not a scala type genius but maybe this works:
implicit def t2mapper[X, A<:X, B<:X](t: (A,B)) = new { def map[A, B, R](f: X => R) = (f(t._1),f(t._2)) }
This can easily be achieved using shapeless, although you'll have to define the mapping function first before doing the map:
object fun extends Poly1 {
implicit def value[S <: Super] = at[S](_.i)
}
(Sub1, Sub2) map fun // typed as (Int, Int), and indeed equal to (1, 2)
(I had to add a val in front of i in the definition of Super, this way: class Super(val i: Int), so that it can be accessed outside)
The deeper question here is "why are you using a Tuple for this?"
Tuples are hetrogenous by design, and can contain an assortment of very different types. If you want a collection of related things, then you should be using ...drum roll... a collection!
A Set or Sequence will have no impact on performance, and would be a much better fit for this kind of work. After all, that's what they're designed for.
For the case when the two functions to be applied are not the same
scala> Some((1, "hello")).map((((_: Int) + 1 -> (_: String).length)).tupled).get
res112: (Int, Int) = (2,5)
The main reason I have supplied this answer is it works for lists of tuples (just change Some to List and remove the get).