I'm trying to understand the following piece of code (from the Scalaz library):
def kleisliIdApplicative[R]: Applicative[Kleisli[Id, R, ?]] = ...
I'm assuming that a type of the form T[P0, ?] is a type-constructor that takes a parameter. However I'm no able to find documentation that explains the usage of question marks in type parameters.
A related question is what is the difference between the question mark and an underscore?
Is there a place where all this is well-documented?
The question mark syntax comes from a compiler plugin called kind-projector.
You can see it being included in the scalaz build here: https://github.com/scalaz/scalaz/blob/series/7.3.x/project/build.scala#L310
The plugin translates
Kleisli[Id, R, ?]
into (roughly)
({type L[A] = Kleisli[Id, R, A]})#L
which is a rather convoluted way (but unfortunately the only way in Scala) of expressing a type lambda, i.e. a partially applied type constructor.
Related
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!
I am nearly completely new to Scala, a few months on. I noticed some wild signatures. I have worked through generics with contrapositive/copositive/extensions/invariance, and most of the basics. However, I continue to find some of the method signatures a bit confusing. While I find examples and know what the signatures produce, I am still a bit at a loss as to some of the functionality. Googling my questions has left me with no answers. I do have the general idea that people like to beat the basic CS 1 stuff to death. I have even tried to find answers on the scala website. Perhaps I am phrasing things like "expanded method signature" and "defining function use in scala signature" wrong. Can anyone explain this signature?
futureUsing[I <: Closeable, R](resource: I)(f: I => Future[R])(implicit ec: ExecutionContext):Future[R]
My guess is that after the initial generics and parameter declaration with a parameter of type I, the body is defined and the final portion is any objects specific to the function or that must be looked up in an implicit scope (are they destroyed afterwards?). Can anyone layout an expanded method signature so I know what code I am using? Is there a particular order the last two parts must be in?
Note
After a bunch more searching, I found a few valid responses I can throw together:
-Scala - Currying and default arguments
-why in Scala a function type needs to be passed in separate group of arguments into a function
There is no set ordering just that implicits must be last. Placement is about dependency which flows left to right as someone down the list in one of the above answers pointed out. Why I cannot have implicits first and everything depending on them afterwards is odd since having nothing available causes an error and things will likely depend on a given implicit.
However, I am still a bit confused. When specifying f: I => Future[R], and needing to supply the last argument, lets pretend it would be any implicit, would I need to do something more like:
futureUsing(resourceOfI)({stuff => doStuff(stuff)})(myImplicit)
Is this even correct?
Could I do:
futureUsing(resourceOfI)(myImplicit)({stuff => doStuff(stuff)})
Why? I am really trying to get at the underlying reasons rather than just a binary yes or no.
Final Note
I just found this answer. It appears the order cannot be changed. Please correct me if I am wrong.
Scala: Preference among overloaded methods with implicits, currying and defaults
Can anyone explain this signature?
futureUsing[I <: Closeable, R]
futureUsing works with two separate types (two type parameters). We don't know exactly what types they are, but we'll call one I (input), which is a (or derived from) Closable, and the other R (result).
(resourse: I)
The 1st curried argument to futureUsing is of type I. We'll call it resourse.
(f: I => Future[R])
The 2nd curried argument, f, is a function that takes an argument of type I and returns a Future that will (eventually) contain something of type R.
(implicit ec: ExecutionContext)
The 3rd curried argument, ec, is of type ExecutionContext. This argument is implicit, meaning if it isn't supplied when futureUsing is invoked, the compiler will look for an ExecutionContext in scope that has been declared implicit and it will pull that in as the 3rd argument.
:Future[R]
futureUsing returns a Future that contains the result of type R.
Is there a specific ordering to this?
Implicit parameters are required to be the last (right most) parameters. Other than that, no, resourse and f could have been declared in either order. When invoked, of course, the order of arguments must match the order as declared in the definition.
Do I need ... implicits to drag in?
In the case of ExecutionContext let the compiler use what's available from import scala.concurrent.ExecutionContext. Only on rare occasions would you need something different.
...how would Scala use the 2nd curried argument...
In the body of futureUsing I would expect to see f(resourse). f takes an argument of type I. resourse is of type I. f returns Future[R] and so does futureUsing so the line f(resourse) might be the last statement in the body of futureUsing.
Looking at the <> method in the following scala slick class, from http://slick.typesafe.com/doc/2.1.0/api/index.html#scala.slick.lifted.ToShapedValue, it reminds me of that iconic stackoverflow thread about scala prototypes.
def <>[R, U](f: (U) ⇒ R, g: (R) ⇒ Option[U])
(implicit arg0: ClassTag[R], shape: Shape[_ <: FlatShapeLevel, T, U, _]):
MappedProjection[R, U]
Can someone bold and knowledgeable provide an articulate walkthrough of that long prototype definition, carefully clarifying all of its type covariance/invariance, double parameter lists, and other advanced scala aspects?
This exercise will also greatly help dealing with similarly convoluted prototypes!
Ok, let's take a look:
class ToShapedValue[T](val value: T) extends AnyVal {
...
#inline def <>[R: ClassTag, U](f: (U) ⇒ R, g: (R) ⇒ Option[U])(implicit shape: Shape[_ <: FlatShapeLevel, T, U, _]): MappedProjection[R, U]
}
The class is an AnyVal wrapper; while I can't actually see the implicit conversion from a quick look, it smells like the "pimp my library" pattern. So I'm guessing this is meant to add <> as an "extension method" onto some (or maybe all) types.
#inline is an annotation, a way of putting metadata on, well, anything; this one is a hint to the compiler that this should be inlined. <> is the method name - plenty of things that look like "operators" are simply ordinary methods in scala.
The documentation you link has already expanded the R: ClassTag to ordinary R and an implicit ClassTag[R] - this is a "context bound" and it's simply syntactic sugar. ClassTag is a compiler-generated thing that exists for every (concrete) type and helps with reflection, so this is a hint that the method will probably do some reflection on an R at some point.
Now, the meat: this is a generic method, parameterized by two types: [R, U]. Its arguments are two functions, f: U => R and g: R => Option[U]. This looks a bit like the functional Prism concept - a conversion from U to R that always works, and a conversion from R to U that sometimes doesn't work.
The interesting part of the signature (sort of) is the implicit shape at the end. Shape is described as a "typeclass", so this is probably best thought of as a "constraint": it limits the possible types U and R that we can call this function with, to only those for which an appropriate Shape is available.
Looking at the documentation forShape, we see that the four types are Level, Mixed, Unpacked and Packed. So the constraint is: there must be a Shape, whose "level" is some subtype of FlatShapeLevel, where the Mixed type is T and the Unpacked type is R (the Packed type can be any type).
So, this is a type-level function that expresses that R is "the unpacked version of" T. To use the example from the Shape documentation again, if T is (Column[Int], Column[(Int, String)], (Int, Option[Double])) then R will be (Int, (Int, String), (Int, Option[Double]) (and it only works for FlatShapeLevel, but I'm going to make a judgement call that that's probably not important). U is, interestingly enough, completely unconstrained.
So this lets us create a MappedProjection[unpacked-version-of-T, U] from any T, by providing conversion functions in both directions. So in a simple version, maybe T is a Column[String] - a representation of a String column in a database - and we want to represent it as some application-specific type, e.g. EmailAddress. So R=String, U=EmailAddress, and we provide conversion functions in both directions: f: EmailAddress => String and g: String => Option[EmailAddress]. It makes sense that it's this way around: every EmailAddress can be represented as a String (at least, they'd better be, if we want to be able to store them in the database), but not every String is a valid EmailAddress. If our database somehow had e.g. "http://www.foo.com/" in the email address column, our g would return None, and Slick could handle this gracefully.
MappedProjection itself is, sadly, undocumented. But I'm guessing it's some kind of lazy representation of a thing we can query; where we had a Column[String], now we have a pseudo-column-thing whose (underlying) type is EmailAddress. So this might allow us to write pseudo-queries like 'select from users where emailAddress.domain = "gmail.com"', which would be impossible to do directly in the database (which doesn't know which part of an email address is the domain), but is easy to do with the help of code. At least, that's my best guess at what it might do.
Arguably the function could be made clearer by using a standard Prism type (e.g. the one from Monocle) rather than passing a pair of functions explicitly. Using the implicit to provide a type-level function is awkward but necessary; in a fully dependently typed language (e.g. Idris), we could write our type-level function as a function (something like def unpackedType(t: Type): Type = ...). So conceptually, this function looks something like:
def <>[U](p: Prism[U, unpackedType(T)]): MappedProjection[unpackedType(T), U]
Hopefully this explains some of the thought process of reading a new, unfamiliar function. I don't know Slick at all, so I have no idea how accurate I am as to what this <> is used for - did I get it right?
everyone . Please forgive me asking a stupid question on Scala.
Though I have been programming in Scala for about 2 years, I still find it hard to understand implicit usage. Let's take an example for discussion:
Array(1,2,3,4).map(x => x)
If you look up the scaladoc, you cant' find the method map on Array class. The reason that map can apply on Array(1,2,3,4) is that there is an implicit function implicit def intArrayOps (xs: Array[Int]): ArrayOps[Int] defined in scala.Predef.
However, there are two parameter lists, where the second one is written as implicit bf: CanBuildFrom[Array[T], B, That]). Now I wonder where the compiler finds a proper argument for type CanBuildFrom when applying map on Array(1,2,3,4).
The implicit resolution includes searching the companion object for the type of the implicit parameter as well as the companion objects for the type parameters of the implicit parameter. In the example above the signature of map is the following
def map[B, That](f: (Int) => B)(implicit bf: CanBuildFrom[Array[Int], B, That]): That
Since we have no type requirements for That we can ignore it for now. After we look in the local and container scopes and find no matching implicits, the next place to look for an implicit would be the companion object for CanBuildFrom. However it has no companion object. So we continue on and look in Array for an implicit. We find one in the form of
implicit def canBuildFrom[T](implicit m: ClassManifest[T]): CanBuildFrom[Array[_], T, Array[T]]
Since we have no type requirements and a matching implicit, "That" is forced to be of type Array[Int] and completes our typing.
This question is partially answered with other question on StackOverflow. Let me give a try to summarize them:
The first part you need to know is where the Scala compiler looks for implicits. You can find some more detail about CanBuildFrom here.
If you have understood what is mentioned in the answers about implicits ‣you should take a look to the construction of Scala Collections. Their inheritance-hierarchy is explained here and for List here. All of them are build up with Builders. This is explained in detail in a question about breakOut.
To round up your knowledge, you should know how to pimp the Collections. Also, this is explained on StackOverflow in this question.
Please note, the best answers on StackOverflow are summarized in the Scala-Tag-Wiki.
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Context bounds shortcut with higher kinded-types
Why doesn't the Scala compiler let me write this?
class TypeCtor[M[_]: ClassManifest]
It complains with “error: type M takes type parameters”. If I'm only asking for the ClassManifest, the compiler should be able to insert it no matter what the parametrization of M is, no?
This works as expected:
class TypeCtor[M[_]](implicit val ev: ClassManifest[M[_]])
(new TypeCtor[Vector]).ev.erasure // => class scala.collection.immutable.Vector
See my answer to this question.
The parameterization of M is indeeed irrelevant, but the Scala compiler needs a parameter for ClassManifest in order to know which manifest to insert. Let's say we have
class TypeCtor[A,B](implicit val ev: ClassManifest)
Now the Compiler would not know whether to insert the Manifest of A or B. Also you can't write ClassManifest[M] because ClassManifest expects a Type of kind * and M has kind * -> *.