Scala type mismatch using multiple generic - scala

I'm trying to use Scala to prototype the functionality of lazy endless list for my lambda calculus classes. The public constructor takes two arguments and should create LazyList[A,A].
class LazyList[A,B] private (private val first: A, private val mapper: A => B, private val successor: A => A) {
def this(first: A, successor: A => A) = this(first, (e: A) => e, successor)
def head: B = mapper(first)
def tail(): LazyList[A,B] = new LazyList(successor(first), mapper, successor)
def map[R](func: B => R) = new LazyList[A, R](first, func.compose(mapper), successor)
def at(index: Long): B = if (index == 0L) head else tail().at(index - 1)
def sublist(end: Long): List[B] = if (end == 0L) List(head) else head :: tail().sublist(end - 1)
override def toString = s"LazyList($first, $mapper, $successor)"
}
But the code compilation fails with error.
Error:(20, 65) type mismatch;
found : e.type (with underlying type A)
required: B
def this(first: A, successor: A => A) = this(first, (e: A) => e, successor)
^
What actually am I doing wrong?

Parameterized signatures inside the class don't have any info about the relation of type B to type A, and thus the compiler generally thinks that everywhere inside the LazyList's body B is not A, that's why it compiler complains when you try to assign A => A to A => B.
You should create an alternative constructor not as this(), but as a factory method in companion object. Note the A of this usage is a parameter which is not in any way related to the A inside LazyList's body:
object LazyList {
def apply[A](first: A, successor: A => A): LazyList[A, A] = new LazyList(first, identity, successor)
}

Related

Scala custom collection fails to pick correct map function in for-comprehension

I've implemented a custom collection class which is basically a Map with implicit integer keys and values that are subclasses of AnyRef. It uses the Int keys as index for underlying array structure. Here is the class declaration signature (class instantiation is done in companion object, hence private constructor):
class ArrayMap[T >: Null <: AnyRef: ClassTag] private (private var data: Array[T]) { self =>
...
}
Now I want to add required methods for for-comprehension. I've defined two different map functions. One that returns a List and the other one returns the same data type (ArrayMap).
def map[X](f: (Int, T) => X): List[X] = { ... }
def map[X >: Null <: AnyRef: ClassTag](f: (Int, T) => X): ArrayMap[X] = { ... }
def foreach(f: (Int, T) => Unit): Unit = { ... }
def flatMap[X >: Null <: AnyRef: ClassTag](f: (Int, T) => Iterable[(Int, X)]): ArrayMap[X] = { ... }
def filter(p: (Int, T) => Boolean): ArrayMap[T] = { ... }
No implicit is defined. Above functions work as expected when used separately. The problem is in for-comprehensions. For loop either picks the first map which returns List or throws a mysterious error. The following example produces error:
val map = ArrayMap.empty[Integer]
map(0) = 0
map(1) = 1
map(5) = 2
map(6) = 3
map(10) = 4
val rs: ArrayMap[String] = for (e <- map) yield e._2.toString
Above code throws:
Error:(293, 41) missing parameter type
val rs: ArrayMap[String] = for (e <- map) yield e._2.toString
What am I missing?
[UPDATE]
The full implementation is available as a gist here.
The problem is related to a type mismatch, you defined the function to pass to map as a function of two arguments (Int & T) to X. while in your for comprehension you treat it as a function of one argument (a tuple (Int, T)) to X.
The simplest solution is to redefine your map function signature. e.g.
import scala.reflect.ClassTag
class ArrayMap[T >: Null <: AnyRef: ClassTag] (val data: Array[T]) {
// Note the double parenthesis (()).
def map[X >: Null <: AnyRef: ClassTag](f: ((Int, T)) => X): ArrayMap[X] = ???
def withFilter(p: ((Int, T)) => Boolean): ArrayMap[T] = ???
}
With that definition you can make something like
val map: ArrayMap[java.lang.Integer] = new ArrayMap(Array(1, 2, 3))
// Note I use lazy val to avoid the NotImplementedException.
lazy val rs1: ArrayMap[String] = map.map(tuple => tuple._2.toString)
lazy val rs2: ArrayMap[String] = map.map { case (_, v) => v.toString }
lazy val rs3: ArrayMap[String] = for {
tuple <- map
} yield tuple._2.toString
lazy val rs4: ArrayMap[String] = for {
(_, v) <- map
} yield v.toString
See the full signature of map in Scala Map as a reference.

writing generic function using method name

I am trying to write the following method:
case class Config2(repoName: String)
def buildAction[A, M, R <: HList]()
(implicit
gen: Generic.Aux[Config2, R],
mod: Modifier.Aux[R, M, A, A, R])
: (A, Config2) => Config2 = {
(arg: A, c: Config2) => {
val rec = mod.apply(gen.to(c), _ => arg)
gen.from(rec)
}
}
When trying to use it with:
buildAction[String, Witness.`'repoName`.T, String :: HList]()
I get an error:
could not find implicit value for parameter gen: shapeless.Generic.Aux[com.advancedtelematic.tuf.cli.Cli.Config2,shapeless.::[String,shapeless.HList]]
[error] val _ = buildAction[String, Witness.`'repoName`.T, String :: HList]()
am I missing some import here?
Second question is, can I somehow rewrite this signature so I don't don't have to specify all the types? In practive the Config2 type takes a long list of fields so it's not pratical to write this all the time
Update:
I simplified this to the following:
val CGen = LabelledGeneric[Config]
def buildAction[A, M]()
(implicit mod: Modifier.Aux[CGen.Repr, M, A, A, CGen.Repr])
: (A, Config) => Config = {
(arg: A, c: Config) => {
val rec = mod.apply(CGen.to(c), _ => arg)
CGen.from(rec)
}
}
Which allows me to just write:
buildAction[String, Witness.`'repoName`.T]()
But I still have to specify that Witness. Is the a way I could write buildAction[String]("repoName") and have some method provide the Witness implicitly?
Update: the following works!
val CGen = LabelledGeneric[Config]
def buildAction[A](witness: Witness)
(implicit mod: Modifier.Aux[CGen.Repr, witness.T, A, A, CGen.Repr]):
(A, Config) => Config = {
(arg: A, c: Config) => {
val rec = mod.apply(CGen.to(c), _ => arg)
CGen.from(rec)
}
}
buildAction[RepoName]('repoName)
am I missing some import here?
No, it's probably just that String :: HList must be String :: HNil
Second question is, can I somehow rewrite this signature so I don't don't have to specify all the types?
You can use a trick known as kinda-curried type parameters:
object buildAction {
class PartiallyApplied[A, M] {
def apply[R <: HList]()(implicit ...)
}
def apply[A, M] = new PartiallyApplied[A, M]
}
Used as
buildAction[String, Witness.`'foo`.T]()
Also, since your code mentions field name, you probably want LabelledGeneric in conjunction with ops.record.Updater

type does not take parameters Scala

I have case class State and want to extend Variable class from it; but in Variable class only need value in constructor. Where can I put run function?
case class State[S, +A](run: S => (A, S)) {
//.....has `map` function
def map[B, X >: State[S, B]](f: A => B): X =
State(state => {
val (a, s2) = run(state)
(f(a), s2)
})
}
class Variable[+A](value: A) extends State[A, A] { // ERROR
def get: Variable[A] =
map(x => x)
def set(newValue: A): Variable[A] =
map(_ => newValue)
}
UPDATE
I've changed to something like this:
class Variable[+A](value: A, run: A => (A, A)) extends State[A, A](run) {
def get: Variable[A] =
map(x => x) // ERROR HERE
def set(newValue: A): State[A, A] =
map(_ => newValue)
}
object Variable {
def create[A](value: A): Variable[A] = new Variable[A](value, x => (x, x))
}
But I've gotten error:
type mismatch; found : com.libs.State[A,A] required: com.libs.Variable[A] Variable.scala /scala/src/com/libs line 4 Scala Problem
The problem is that you cannot define a Variable using map, since map defines a State which is only a super-type of Variable. How can your program know how to set the additional information of your subclass, using only map?
However, if you define type Variable[+A] = State[A, A], so that it is not a subclass but an alias for the same class, you will have some variance errors, since State is invariant in its type parameter S, so Variable must be too.

Correct encoding of this existential type in Scala?

I'm interested in encoding this Stream type from the Stream Fusion paper from Coutts et al. I'm exploring stream fusion in Scala, attempting to use macros in place of GHC's rewrite rules.
data Stream a = āˆƒs. Stream (s ā†’ Step a s) s
data Step a s = Done
| Yield a s
| Skip s
I've tried a few different approaches but I'm not sure how to encode the type of Stream in Scala such that both occurrences of S refer to the same type. I've written the Step type easily as.
sealed abstract class Step[+A, +S]
case object Done extends Step[Nothing, Nothing]
case class Yield[A, S](a: A, s: S) extends Step[A, S]
case class Skip[S](s: S) extends Step[Nothing, S]
So far this type seems correct. I've used covariance so that a function of type A => A will work even if we receive a Yield and return a Done or Step. Just like in Haskell.
My sticking point has been the signature of Stream. I've been attempting to define it as just a case class. The only signature that has worked so far is using an Exists type operator and Tuple to perserve the equality of type S in both components as below.
type Exists[P[_]] = P[T] forSome { type T }
case class Stream[A](t: Exists[({ type L[S] = (S => Step[A, S], S)})#L])
Is there a way to encode it such that the tuple is not needed? Something closer to Haskell's (assuming existential operator) this:
case class Stream(āˆƒ S. f: S => Step[A, S], s: S)
where each member can be separate field.
It also occurs to me that I could encode this in an SML Module/Functor style like so:
trait Stream[A] {
type S <: AnyRef
val f: S => Step[A, S]
val s: S
}
object Stream {
def apply[A, S1 <: AnyRef](next: S1 => Step[A, S1], st: S1): Stream[A] = new Stream[A] {
type S = S1
val f = next
val s = st
}
def unapply[A](s: Stream[A]): Option[(s.f.type, s.s.type)] = Some(s.f, s.s)
}
but this is a little more complicated. I was hoping there exists a clearer way, that I am ignorant of. Also as I attempted to explore this path, I had to do a few things to satisfy the compiler such as add the AnyRef bound, and the unapply method doesn't work. With this error message from scalac:
scala> res2 match { case Stream(next, s) => (next, s) }
<console>:12: error: error during expansion of this match (this is a scalac bug).
The underlying error was: type mismatch;
found : Option[(<unapply-selector>.f.type, <unapply-selector>.s.type)]
required: Option[(s.f.type, s.s.type)]
res2 match { case Stream(next, s) => (next, s) }
^
First off, Step looks perfect to me. As for Stream, I think you're on the right track with the abstract type. Here's what I came up with (including implementations of the remaining methods in section 2.1 of the Coutts paper):
abstract class Stream[A] {
protected type S
def next: S => Step[A, S]
def state: S
def map[B](f: A => B): Stream[B] = {
val next: S => Step[B, S] = this.next(_) match {
case Done => Done
case Skip(s) => Skip(s)
case Yield(a, s) => Yield(f(a), s)
}
Stream(next, state)
}
def unstream: List[A] = {
def unfold(s: S): List[A] = next(s) match {
case Done => List.empty
case Skip(s) => unfold(s)
case Yield(a, s) => a :: unfold(s)
}
unfold(state)
}
}
object Stream {
def apply[A, S0](n: S0 => Step[A, S0], s: S0) = new Stream[A] {
type S = S0
val next = n
val state = s
}
def apply[A](as: List[A]): Stream[A] = {
val next: List[A] => Step[A, List[A]] = {
case a :: as => Yield(a, as)
case Nil => Done
}
Stream(next, as)
}
def unapply[A](s: Stream[A]): Option[(s.S => Step[A, s.S], s.S)] =
Some((s.next, s.state))
}
A couple things to note:
My unapply has a dependent method type: it depends on the s.S. I think that might have been your stumbling block.
The unfold method in unstream is not tail-recursive.
The thing I'm still not really clear on myself is why it's important for S to be existential / hidden / whatever. If it's not, you could just write:
case class Stream[A, S](next: S => Step[A, S], state: S)
... but I assume there's a reason for it. That being said, I'm also not sure this approach actually hides S the way you want. But this is my story and I'm sticking to it.

General 'map' function for Scala tuples?

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