Can someone explain weird construction of structural type nested in generics:
implicit def Function1Functor[R]: Functor[({type λ[α]=(R) => α})#λ] =
new Functor[({type λ[α]=(R) => α})#λ] ....
This example comes from Scalaz library: Functor.scala
Why this construction is needed there? Wouldn't be simpler to write:
implicit def Function1Functor[R,A]: Functor[R =>A]
or
implicit def Function1Functor[R,A]: Functor[Function1[R,A]]
The signature of the Functor type constructor shows that it is parameterised with another, unary, type constructor F:
trait Functor[F[_]] extends InvariantFunctor[F]
Neither R => A nor Function1[R,A] are type constructors; they take no parameters.
However in:
type λ[α] = (R) => α
λ is a type constructor taking one parameter, α. (R is already defined in this context.)
The syntax ({type λ[α]=(R) => α})#λ is known as a type lambda. It is a syntactic trick allowing a type alias to be created inline and referred to via a projection, so the whole expression can be used where a type is required.
Related
I'm pretty sure I'm missing something here, since I'm pretty new to Shapeless and I'm learning, but when is the Aux technique actually required? I see that it is used to expose a type statement by raising it up into the signature of another "companion" type definition.
trait F[A] { type R; def value: R }
object F { type Aux[A,RR] = F[A] { type R = RR } }
but isn't this nearly equivalent to just putting R in the type signature of F ?
trait F[A,R] { def value: R }
implicit def fint = new F[Int,Long] { val value = 1L }
implicit def ffloat = new F[Float,Double] { val value = 2.0D }
def f[T,R](t:T)(implicit f: F[T,R]): R = f.value
f(100) // res4: Long = 1L
f(100.0f) // res5: Double = 2.0
I see that path-dependent type would bring benefits if one could use them in argument lists, but we know we can't do
def g[T](t:T)(implicit f: F[T], r: Blah[f.R]) ...
thus, we are still forced to put an additional type parameter in the signature of g. By using the Aux technique, we are also required to spend additional time writing the companion object. From a usage standpoint, it would look to a naive user like me that there is no benefit in using path-dependent types at all.
There is only one case I can think of, that is, for a given type-level computation more than one type-level result is returned, and you may want to use only one of them.
I guess it all boils down to me overlooking something in my simple example.
There are two separate questions here:
Why does Shapeless use type members instead of type parameters in some cases in some type classes?
Why does Shapeless include Aux type aliases in the companion objects of these type classes?
I'll start with the second question because the answer is more straightforward: the Aux type aliases are entirely a syntactic convenience. You don't ever have to use them. For example, suppose we want to write a method that will only compile when called with two hlists that have the same length:
import shapeless._, ops.hlist.Length
def sameLength[A <: HList, B <: HList, N <: Nat](a: A, b: B)(implicit
al: Length.Aux[A, N],
bl: Length.Aux[B, N]
) = ()
The Length type class has one type parameter (for the HList type) and one type member (for the Nat). The Length.Aux syntax makes it relatively easy to refer to the Nat type member in the implicit parameter list, but it's just a convenience—the following is exactly equivalent:
def sameLength[A <: HList, B <: HList, N <: Nat](a: A, b: B)(implicit
al: Length[A] { type Out = N },
bl: Length[B] { type Out = N }
) = ()
The Aux version has a couple of advantages over writing out the type refinements in this way: it's less noisy, and it doesn't require us to remember the name of the type member. These are purely ergonomic issues, though—the Aux aliases make our code a little easier to read and write, but they don't change what we can or can't do with the code in any meaningful way.
The answer to the first question is a little more complex. In many cases, including my sameLength, there's no advantage to Out being a type member instead of a type parameter. Because Scala doesn't allow multiple implicit parameter sections, we need N to be a type parameter for our method if we want to verify that the two Length instances have the same Out type. At that point, the Out on Length might as well be a type parameter (at least from our perspective as the authors of sameLength).
In other cases, though, we can take advantage of the fact that Shapeless sometimes (I'll talk about specifically where in a moment) uses type members instead of type parameters. For example, suppose we want to write a method that will return a function that will convert a specified case class type into an HList:
def converter[A](implicit gen: Generic[A]): A => gen.Repr = a => gen.to(a)
Now we can use it like this:
case class Foo(i: Int, s: String)
val fooToHList = converter[Foo]
And we'll get a nice Foo => Int :: String :: HNil. If Generic's Repr were a type parameter instead of a type member, we'd have to write something like this instead:
// Doesn't compile
def converter[A, R](implicit gen: Generic[A, R]): A => R = a => gen.to(a)
Scala doesn't support partial application of type parameters, so every time we call this (hypothetical) method we'd have to specify both type parameters since we want to specify A:
val fooToHList = converter[Foo, Int :: String :: HNil]
This makes it basically worthless, since the whole point was to let the generic machinery figure out the representation.
In general, whenever a type is uniquely determined by a type class's other parameters, Shapeless will make it a type member instead of a type parameter. Every case class has a single generic representation, so Generic has one type parameter (for the case class type) and one type member (for the representation type); every HList has a single length, so Length has one type parameter and one type member, etc.
Making uniquely-determined types type members instead of type parameters means that if we want to use them only as path-dependent types (as in the first converter above), we can, but if we want to use them as if they were type parameters, we can always either write out the type refinement (or the syntactically nicer Aux version). If Shapeless made these types type parameters from the beginning, it wouldn't be possible to go in the opposite direction.
As a side note, this relationship between a type class's type "parameters" (I'm using quotation marks since they may not be parameters in the literal Scala sense) is called a "functional dependency" in languages like Haskell, but you shouldn't feel like you need to understand anything about functional dependencies in Haskell to get what's going on in Shapeless.
In Scala, an existential type has the following two forms:
// placeholder syntax
List[_]
// forSome
List[T forSome {type T}]
However, seems that the second form can not appear in the method type parameter position(at least in the way like I write below).
// placeholder syntax is Okay
scala> def foo[List[_]](x: List[_]) = x
foo: [List[_]](x: List[_])List[_]
scala> def foo[List[t forSome {type t}]](x: List[_]) = x
<console>:1: error: ']' expected but 'forSome' found.
def foo[List[T forSome {type T}]](x: List[_]) = x
^
// being as upper bound is also Okay
scala> def foo[A <: List[T forSome { type T }]](x: A) = x
foo: [A <: List[T forSome { type T }]](x: A)A
// type alias is a possible way but that is not what I want
scala> type BB = List[T forSome {type T}]
defined type alias BB
scala> def foo[BB](x: List[_]) = x
foo: [BB](x: List[_])List[Any]
I have tried for a while but been unable to find the right way to get the second compiled successfully.
So is it just some restrictions about method type parameter, or am i missing something here.
The confusion is that the underscore (_) in foo does not denote an existential type.
Let's see what the following actually means:
def foo[List[_]](x: List[_]) = x
List here is a higher kinded type parameter (and by the way does not refer to scala's built-in List type -- aka scala.collection.immutable). This type parameter itself has a single type parameter, denoted by the underscore (_).
Now that it's clear that List[_] is not an existential here, it follows that forSome has no business going there.
However, you can use forSome in the type of x. The following is equivalent to your original definition of foo:
def foo[List[_]](x: List[T] forSome { type T }) = x
Then again, this is probably still not what you'd want, seeing as List is still a type parameter and not scala.collection.immutable. What you'd probably want is:
def foo(x: List[T] forSome { type T }) = x
which is the same as:
def foo(x: List[_]) = x
Hinted by Régis Jean-Gilles's "List here is a higher-kinded type parameter (and by the way does not refer to Scala's built-in List type -- aka scala.collection.immutable)", I had a re-check on the definition of existential type and finally figured out the problem in my case, just write it here as complement for Régis Jean-Gilles's answer.
Existential types are a means of constructing types where portions of the type signature are existential, where existential means that although some real type meets that portion of a type signature, we don’t care about the specific type. Existential types were introduced into Scala as a means to interoperate with Java’s generic types, such as Iterator<?> or Iterator<? extends Component>(Quote from <<Scala In Depth>>).
Real type could be type from the library(like the scala.collection.immutable.List), or the self-defined type like type alias BB in my case. Anyway, Scala compiler has to guarantee that part of the existential type is also known.
The problem in my case is that
// List is type parameter which accepts another type as parameter
def foo[List[_]](x: List[_]) = x
// List may be misleading here, just change it to another name
def foo[TT[_]](x: TT[_]) = x
Scala compiler only knows that TT is higher-kinded type parameter, apparently no real type exists here. So in this case, TT[_] is not a existential type therefore forSome form can not be used in the type parameter position.
And the following cases are valid.
// we define a higher-kined type HKT, so HKT is a real type
// when Scala compiler checks the method parameter part
// HKT can be defined as existential type
def foo[HKT[_]](x: HKT[T forSome { type T }]) = x
def foo[HKT[_]](x: HKT[T] forSome { type T }) = x
This is a follow-up to my previous question
I would like to generalize the implicit conversion toApplicative, which adds method <*> to any M[A=>B], where M is Applicative (i.e. there is a typeclass instance Applicative[M])
implicit def toApplicative[M[_], A, B](mf: M[A=>B])(implicit apm: Applicative[M]) =
new { def<*>(ma: M[A]) = apm.ap(ma)(mf) }
Unfortunately I have got an error:
<console>:25: error: Parameter type in structural refinement
may not refer to an abstract type defined outside that refinement
How would you suggest implement such an implicit conversion ?
The types M and A are referenced from your def so they need to be part of the thing you're returning. I can't see any way to do this completely with the structural refinement, so I think you have to define a parametrized class; how about defining an implicit class rather than the implicit def?
implicit class PimpedApplicative[M[_]: Applicative, A, B](mf: M[A => B]) {
def <*>(ma: M[A]) = Applicative[M].ap(ma)(mf)
}
Lets assume I have instance of arbitrary one-argument generic class (I'll use List in demonstration but this can me any other generic).
I'd like to write generic function that can take instances (c) and be able to understand what generic class (A) and what type argument (B) produced the class (C) of that instance.
I've come up with something like this (body of the function is not really relevant but demonstrates that C conforms to A[B]):
def foo[C <: A[B], A[_], B](c: C) {
val x: A[B] = c
}
... and it compiles if you invoke it like this:
foo[List[Int], List, Int](List.empty[Int])
... but compilation fails with error if I omit explicit type arguments and rely on inference:
foo(List.empty[Int])
The error I get is:
Error:Error:line (125)inferred kinds of the type arguments (List[Int],List[Int],Nothing) do not conform to the expected kinds of the type parameters (type C,type A,type B).
List[Int]'s type parameters do not match type A's expected parameters:
class List has one type parameter, but type A has one
foo(List.empty[Int])
^
Error:Error:line (125)type mismatch;
found : List[Int]
required: C
foo(List.empty[Int])
^
As you can see Scala's type inference cannot infer the types correctly in this case (seems like it's guess is List[Int] instead of List for 2nd argument and Nothing instead of Int for 3rd).
I assume that type bounds for foo I've come up with are not precise/correct enough, so my question is how could I implement it, so Scala could infer arguments?
Note: if it helps, the assumption that all potential generics (As) inherit/conform some common ancestor can be made. For example, that A can be any collection inherited from Seq.
Note: the example described in this question is synthetic and is a distilled part of the bigger problem I am trying to solve.
This is a known limitation of current Scala's type inference for type constructors. Defining the type of formal parameter c as C only collects type constraints for C (and indirectly to A) but not B. In other words List[Int] <: C => { List[Int] <: C <: Any, C <: A[_] <: Any }.
There is a pretty simple translation that allows to guide type inference for such cases. In your case it is:
def foo[C[_] <: A[_], A[_], B](c: A[B]) { val x: A[B] = c }
Same semantics, just slightly different type signature.
In addition to hubertp answer, you can fix you function by removing obsolete (in you example) type variable C, e.g:
def foo[A[_], B](c: A[B]) {
val x: A[B] = c
}
In this case scalac would infer A[_] as List and B as Int.
Update (according to the comment).
If you need an evidence that C is subtype of A[B], then use implicit:
def foo[A[_], B, C](c: C)(implicit ev: C <:< A[B]) = {
val x: A[B] = c
}
Then it won't compile this:
scala> foo[List, String, List[Int]](List.empty[Int])
<console>:9: error: Cannot prove that List[Int] <:< List[String].
foo[List, String, List[Int]](List.empty[Int])
Consider the following Scala code (e.g., in REPL)
object A{def foo:Unit = {}}
object B{def foo:Unit = {}}
def bar[T <: Any {def foo: Unit}](param: T*):Unit = param.foreach(x => x.foo)
bar(A, A) // works fine
bar(B, B) // works fine
bar(A, B) // gives error
The first two work fine. The third ones gives an error:
error: inferred type arguments [ScalaObject] do not conform to method bar's type parameter bounds [T <: Any{def foo: Unit}]
Are there any ways to do what I want?
This is usually called structural typing, not duck typing. I edited your title. :)
I think that your problem is caused by defining the type parameter T and then using it in an invariant way. T can only refer to one concrete type, but you have parameters of different types A and B.
This works:
def bar(param: {def foo: Unit}*) = param.foreach(x => x.foo)
Edit: Using a type alias also works:
type T = {def foo: Unit}
def bar(param: T*) = param.foreach(x => x.foo)
This works because the compiler will simply substitute the structural type in place of its alias, T. After the substitution, this example is exactly the same as the one above.