Scala recursive type alias error - scala

I have a couple of functions whose only parameter requirement is that it has some sort of collection that is also growable (i.e. it could be a Queue, List, PriorityQueue, etc.), so I attempted to create the following type alias:
type Frontier = Growable[Node] with TraversableLike[Node, Frontier]
to use with function definitions like so:
def apply(frontier: Frontier) = ???
but the type alias returns the error "Illegal cyclic reference involving type Frontier." Is there any way to get around the illegal cyclic reference to use the type alias or something similar to it?
One solution is to use the following:
def apply[F <: Growable[Node] with TraversableLike[Node, F]](f: F) = ???
but this seems to add unnecessary verbosity when the function definition is doing seemingly the exact same thing as the type alias. The type is also used in other places, so a type alias would greatly increase readability.

From section 4.3 of the spec:
The scope rules for definitions (§4) and type parameters (§4.6) make
it possible that a type name appears in its own bound or in its
right-hand side. However, it is a static error if a type alias refers
recursively to the defined type constructor itself.
So no, there's no way to do this directly, but you can accomplish much the same thing with a type parameter on the type alias:
type Frontier[F <: Frontier[F]] = Growable[Int] with TraversableLike[Int, F]
Now you just write your apply like this:
def apply[F < Frontier[F]](frontier: F) = ???
Still a more little verbose than your hypothetical first version, but shorter than writing the whole thing out.
You could also just use the wildcard shorthand for an existential type:
type Frontier = Growable[Node] with TraversableLike[Node, _]
Now your first apply will work as it is. You're just saying that there has to be some type that fits that slot, but you don't care what it is.
In this case specifically, though, is there a reason you're not using Traversable[Node] instead? It would accomplish practically the same thing, and isn't parameterized on its representation type.

Related

def layout[A](x: A) = ... syntax in Scala

I'm a beginner of Scala who is struggling with Scala syntax.
I got the line of code from https://www.tutorialspoint.com/scala/higher_order_functions.htm.
I know (x: A) is an argument of layout function
( which means argument x of Type A)
But what is [A] between layout and (x: A)?
I've been googling scala function syntax, couldn't find it.
def layout[A](x: A) = "[" + x.toString() + "]"
It's a type parameter, meaning that the method is parameterised (some also say "generic"). Without it, compiler would think that x: A denotes a variable of some concrete type A, and when it wouldn't find any such type it would report a compile error.
This is a fairly common thing in statically typed languages; for example, Java has the same thing, only syntax is <A>.
Parameterized methods have rules where the types can occur which involve concepts of covariance and contravariance, denoted as [+A] and [-A]. Variance is definitely not in the scope of this question and is probably too much for you too handle right now, but it's an important concept so I figured I'd just mention it, at least to let you know what those plus and minus signs mean when you see them (and you will).
Also, type parameters can be upper or lower bounded, denoted as [A <: SomeType] and [A >: SomeType]. This means that generic parameter needs to be a subtype/supertype of another type, in this case a made-up type SomeType.
There are even more constructs that contribute extra information about the type (e.g. context bounds, denoted as [A : Foo], used for typeclass mechanism), but you'll learn about those later.
This means that the method is using a generic type as its parameter. Every type you pass that has the definition for .toString could be passed through layout.
For example, you could pass both int and string arguments to layout, since you could call .toString on both of them.
val i = 1
val s = "hi"
layout(i) // would give "[1]"
layout(s) // would give "[hi]"
Without the gereric parameter, for this example you would have to write two definitions for layout: one that accepts integers as param, and one that accepts string as param. Even worse: every time you need another type you'd have to write another definition that accepts it.
Take a look at this example here and you'll understand it better.
I also recomend you to take a look at generic classes here.
A is a type parameter. Rather than being a data type itself (Ex. case class A), it is generic to allow any data type to be accepted by the function. So both of these will work:
layout(123f) [Float datatype] will output: "[123]"
layout("hello world") [String datatype] will output: "[hello world]"
Hence, whichever datatype is passed, the function will allow. These type parameters can also specify rules. These are called contravariance and covariance. Read more about them here!

Parameterized Type Aliases - Clarification Requested

Consider the following 2 type alias declarations:
type Id[A] = A
type Swap[m[_, _], a, b] = m[b, a]
I'm having a difficult time understanding exactly what these mean. The first one seems to define 'Id' as an alias for the abstract simple type 'A'. But Id is parameterized by the same abstract type. So I'm not understanding exactly what Id is and how it would be used. Perhaps someone could provide some examples?
The second example comes from the language spec and is accompanied with the following text:
... Type constructors are another example, as one can write type Swap[m[_,
_], a,b] = m[b, a], but there is no syntax to write the corresponding anonymous type function directly.
So, again, I'm confused as to what Swap is actually aliasing and how this or a similar declaration would be useful (and how it would be used). Also, what is an anonymous type function?
Thanks.

Scala type system, constrain member's type by parameter of own type

Not really sure the standard terminology here, so I'll try to describe what I'm trying to do. In case you're curious, the app I'm actually trying to write is an asynchronous task queue similar to Resque or rq.
I have a type TaskDef[ArgsT <: AnyVal, ResultT <: AnyVal]. In case you're curious, TaskDef represents "how to execute an asynchronous task which takes argument type ArgsT and result type ResultT, or, the code behind a task".
I'm trying to define a type TaskInst[DefT <: TaskDef]. In case you're curious, TaskInst represents "a TaskDef and associated argument to run it with, or, an actual task instance being submitted to the queue". TaskInst has two members, definition: DefT and arguments whose type I cannot write in code.
In English, my desired constraint is: "For a given DefT, where DefT is some TaskDef[ArgsT, ResultT], TaskInst[DefT] should contain a DefT and an ArgsT". That is, the argument type of the task definition should match the type of the argument given to the task.
How do I express this in the Scala type system?
Alternatively, am I modeling my domain incorrectly and attempting to do something un-idiomatic? Would some alternative approach be more idiomatic?
Thanks in advance!
EDIT:
I think my historical self writing Java would probably have resorted to unchecked casts at this point. This is definitely feasible with some amount of unchecked casts and just leaving out the constraint between the type of the TaskInst's arguments vs the type of the embedded TaskDef's arguments. But, I do wonder whether this is something the compiler can enforce, and hopefully without too scary a syntax.
Define them as abstract types:
trait TaskDef {
type Arguments <: AnyVal
type Result <: AnyVal
}
Then use a type projection:
trait TaskInst[DefT <: TaskDef] {
def definition: DefT
def arguments: DefT#Arguments
}
Live Demo
An add-on to the answer that #rightfold gave:
If you are looking to use type parameters throughout, you will need to properly pass the type parameters through to the type constructors.
Excuse me, that's a bit ambiguous for me to say it that way, so let me use my current code as a concrete example.
trait TaskDef[ArgT_, ResT_] {
type ArgT = ArgT_
type ResT = ResT_
val name: String
def exec(arg: ArgT): String \/ ResT
}
class TaskInst[ArgT, ResT, DefT <: TaskDef[ArgT, ResT]] (
val id: UUID,
val defn: DefT,
val arg: ArgT
)
The main divergence of my current code from #rightfold's example is that TaskDef takes type parameters. Then, when TaskInst's declaration references TaskDef, it must provide appropriate types to the type constructor.
I initially made the mistake of passing in placeholders. That is, I was writing class TaskInst[DefT <: TaskDef[_, _]. Turns out, this doesn't mean what I thought it meant. (I don't know. Perhaps others might be inclined to follow the same line of thought. So, this is just a warning not to.) Don't do that, because then scalac will interpret the expected to mean a generated placeholder (which, as you might imagine, nothing matches), and then you get an obscure error message like the following.
[error] /Users/mingp/Code/scala-redis-queue/src/main/scala/io/mingp/srq/core/TaskInst.scala:8: type mismatch;
[error] found : TaskInst.this.arg.type (with underlying type _$1)
[error] required: _$1
[error] val arg: DefT#ArgT_
[error] ^
[error] one error found
Just posting this in hopes that future readers don't fall into the same hole I did.
EDIT:
As a further addendum, now that I've tried it out for a day, my impression is that this isn't actually a good data model for asynchronous tasks. You're better off combining, since stand-alone instances of TaskDef aren't really useful.

How to check whether (type of) a manifest is a subtype of manifest[Numberic[_]]?

First of all, I know that manifests are deprecated and it is better to use TypeTag, but for now, it is not an option for me, so please consider my problem:
How to check whether type represented by a manifest is a subtype of the type represented by manifest[Numberic[_]]?
Actually, I have a function that receives a manifest and I want to check whether it is numeric or not.
def isNumeric(m: Manifest[T]) : Boolean = m <:< manifest[Numeric[_]]
But, it does not work, e.g. for an input of manifest[Double].
Any idea, how to make it work?
Numeric is a type class and it has nothing with subtyping and Manifest (or TypeTag).
Double is not a Numeric. T : Numeric in type parameter means there is implicit value of type Numeric[T] in scope. You can't check it via reflection.
Maybe you could search for implicit in macros, but I'm not sure and I don't think it's what you are looking for.
So the answer is: You just can't.
It isn't possible even in theory: there is no information about implicit values in runtime and there is no instance of Manifest[T] in compile time.

How to specify bound for a generic type with generic type in Scala?

This question is about working with generic types and setting the bound, so please do not freak out because of the library I use. Treat it as an example.
I work with Scalala and use such types DenseMatrix[V], DenseVectorCol[V] and DenseVectorRow[V]. The common super type for them is Tensor[K,V]. Note that the Tensor has additional parameter K -- all the mentioned classes Dense... set this type K by themselves.
So I would like to write a method with argument which upper type bound is Tensor. I wrote such code for my method:
def validate[K,T <: Tensor[K,Double]](tensor : T) : T = ...
with such intention -- T has to be subtype of Tensor, and I know I work with Doubles all the time, so let it be Double, and for first type argument (K) get it from passed argument.
It does not work as I expected because I get error:
inferred type arguments [Nothing,DenseVectorCol[Double]] do not conform to method validate's type parameter bounds [K,T <: Tensor[K,Double]]
QUESTION: so how to extract this type K from the passed argument?
If you don't care about K at all, you can use a wildcard:
def validate[T <: Tensor[_, Double]]: T = ...
Note that in some cases this wouldn't work (e.g., if you needed to return a K or otherwise use it in the method), but assuming this isn't one of those cases, this is a perfectly valid solution and the type inference will work out just fine.