I am getting the following compile time error in the code below
Error:(7, 29) not found: value Cons
def ::[B >: A](head: B) = Cons[B](head, this)
package basics
sealed trait List[+A] {
import Types._
def ::[B >: A](head: B) = Cons[B](head, this)
def foreach(f: A => Unit): Unit = {
this match {
case x :: t => {
f(x)
t foreach f
}
case Nil => ()
}
}
}
object Types {
type Cons[A] = ::[A]
}
case class ::[+A](head: A, tail: List[A]) extends List[A]
object Nil extends List[Nothing]
object Application {
def main(args: Array[String]): Unit ={
println("hello")
3 :: Nil
}
}
Cons is a type alias not a value. It cannot occur on value position. For example:
I made a few modifications to your program to make it work:
case class ::[+A](head: A, tail: List[A]) extends List[A]
object Nil extends List[Nothing]
object Types {
type Cons[A] = ::[A]
def cons[A](head: A, tail: List[A]) = ::(head,tail)
}
sealed trait List[+A] {
import Types._
def ::[B >: A](head: B):Cons[B] = cons[B](head, this)
}
In def ::[B >: A](head: B):Cons[B] = cons[B](head, this), :Cons[B] illustrates one correct use case of a type alias.
Another problem with your program is the existence of two :: overloaded symbols in the same scope, that's why it required the creation of Types.cons, otherwise the Scala compiler thinks we are trying to invoke List#::
Here is a example from the REPL:
scala> 3 :: Nil
res0: Types.Cons[Int] = ::(3,Nil$#46fd71)
scala> 3 :: 4 :: Nil
res1: Types.Cons[Int] = ::(3,::(4,Nil$#46fd71))
See the type of the expressions is Cons[Int].
The reason is that
object Types {
type Cons[A] = ::[A]
}
is declaration of a type, but Cons in
def ::[B >: A](head: B) = Cons[B](head, this)
is reference to constructor. If you replace it with reference to actual constructor.
Add method def Cons[A] = ::[A] to Types and all will work just fine.
A better alternative to defining def Cons[A] = ::[A] is val Cons = ::. This allows not just writing Cons[B](head, this), but pattern matching
this match {
case Cons(x, t) => ...
case Nil => ...
}
and access to any other methods defined on the :: companion object using Cons name. This is also what Scala standard library does:
type Map[A, +B] = immutable.Map[A, B]
type Set[A] = immutable.Set[A]
val Map = immutable.Map
val Set = immutable.Set
Related
I had a problem coding a function called head, that basically replace the head elements with another for the List invoking it:
List(1,2,3,4).head(4) // List(4,2,3,4)
The code is obviously useless, I was just trying to have fun with Scala. This is the code:
sealed trait List[+A]{
def tail():List[A]
def head[A](x:A):List[A]
}
object Nil extends List[Nothing]{
def tail() = throw new Exception("Nil couldn't has tail")
def head[A](x:A): List[A] = List(x)
}
case class Cons[+A](x :A, xs: List[A]) extends List[A]{
def tail():List[A] = xs
def head[A](a:A): List[A] = Cons(a,xs)
}
object List{
def apply[A](as:A*):List[A] = {
if (as.isEmpty) Nil
else Cons(as.head,apply(as.tail: _*))
}
}
Cons(1,Cons(2,Nil)) == List(1,2)
Cons(1,Cons(2,Cons(3,Cons(4,Nil)))).tail()
List(1,2,3,4,5,6,7).tail()
List(1,2,3,4).head(4)
It doesn't not compile and I have this error:
Error:(11, 39) type mismatch;
found : A$A318.this.List[A(in class Cons)]
required: A$A318.this.List[A(in method head)]
def head[A](a:A): List[A] = Cons(a,xs)
Could you explain why, please?
Regards.
Your problem is that your head method is taking another type A, therefore inside that scope the compiler takes those As as different, i.e., the A defined in the trait is shadowed by the A in head[A].
Also, your head method is taking a covariant element of type A in a contravariant position, so you can't define head as such.
What you can do is defining your head as:
def head[B >: A](x: B): List[B]
Hence, you get:
object S {
sealed trait List[+A] {
def tail(): List[A]
def head[B >: A](x: B): List[B]
}
case object Nil extends List[Nothing] {
def tail() = throw new Exception("Nil doesn't have a tail")
def head[B >: Nothing](x: B): List[B] = Cons(x, Nil)
}
case class Cons[+A](x: A, xs: List[A]) extends List[A] {
def tail(): List[A] = xs
def head[B >: A](a: B): List[B] = Cons(a, xs)
}
object List {
def apply[A](as: A*): List[A] = {
if (as.isEmpty) Nil
else Cons(as.head, apply(as.tail: _*))
}
}
}
Testing this on the REPL:
scala> :load test.scala
Loading test.scala...
defined object S
scala> import S._
import S._
scala> Nil.head(1)
res0: S.List[Int] = Cons(1,Nil)
scala> Cons(1, Nil).head(4)
res1: S.List[Int] = Cons(4,Nil)
You method head does not need a type parameter, since you already have one defined in the class definition and that is exactly the type you want head to receive (if you want head to create a list of the same type of the original).
The error you get is because A is two different types in the context of the method head (the one from the method and the other from the class).
The definition for head should be:
def head(x:A):List[A]
This is continuation of Diverging implicit expansion for type class. I've came up with another version that still doesn't compile, but now for another reason, hence a different question. Here's what I did:
I've basically added a new typeclass NestedParser for the cases where some case class consists of other case classes.
trait Parser[A] {
def apply(s: String): Option[A]
}
trait NestedParser[A] {
def apply(s: String): Option[A]
}
object Parser {
def apply[A](s: String)(implicit parser: Parser[A]): Option[A] = parser(s)
}
object NestedParser {
def apply[A](s: String)(implicit parser: NestedParser[A]): Option[A] = parser(s)
}
I've changed the previous implicit function to return the NestedParser to avoid diverging implicit expansions. Otherwise it's same as before:
implicit def nestedCaseClassParser[A, B, C]
(
implicit pb: Parser[B],
pc: Parser[C],
gen: Generic.Aux[A, B :: C :: HNil]
): NestedParser[A] = new NestedParser[A] {
override def apply(s: String): Option[A] = {
val tmp = s.span(_ != '|') match {
case (h, t) =>
for {
a <- pb(h)
b <- pc(t.substring(1))
} yield a :: b :: HNil
}
tmp.map(gen.from)
}
}
Case classes are same as before:
case class Person(name: String, age: Int)
case class Family(husband: Person, wife: Person)
Now when I try to parse the Family, I get the following compile error:
scala> NestedParser[Family]("")
<console>:32: error: could not find implicit value for parameter parser: NestedParser[Family]
NestedParser[Family]("")
However, it doesn't make sense to me. The function above clearly provides the implicit instance of NestedParser. Why doesn't it satisfy the compiler?
Well, as far as I can see you are not providing any implicit Parser instances which nestedCaseClassParser requires.
I am currently implementing a library to serialize and deserialize to and from XML-RPC messages. It's almost done but now I am trying to remove the boilerplate of my current asProduct method using Shapeless. My current code:
trait Serializer[T] {
def serialize(value: T): NodeSeq
}
trait Deserializer[T] {
type Deserialized[T] = Validation[AnyErrors, T]
type AnyErrors = NonEmptyList[AnyError]
def deserialize(from: NodeSeq): Deserialized[T]
}
trait Datatype[T] extends Serializer[T] with Deserializer[T]
// Example of asProduct, there are 20 more methods like this, from arity 1 to 22
def asProduct2[S, T1: Datatype, T2: Datatype](apply: (T1, T2) => S)(unapply: S => Product2[T1, T2]) = new Datatype[S] {
override def serialize(value: S): NodeSeq = {
val params = unapply(value)
val b = toXmlrpc(params._1) ++ toXmlrpc(params._2)
b.theSeq
}
// Using scalaz
override def deserialize(from: NodeSeq): Deserialized[S] = (
fromXmlrpc[T1](from(0)) |#| fromXmlrpc[T2](from(1))
) {apply}
}
My goal is to allow the user of my library to serialize/deserialize case classes without force him to write boilerplate code. Currently, you have to declare the case class and an implicit val using the aforementioned asProduct method to have a Datatype instance in context. This implicit is used in the following code:
def toXmlrpc[T](datatype: T)(implicit serializer: Serializer[T]): NodeSeq =
serializer.serialize(datatype)
def fromXmlrpc[T](value: NodeSeq)(implicit deserializer: Deserializer[T]): Deserialized[T] =
deserializer.deserialize(value)
This is the classic strategy of serializing and deserializing using type classes.
At this moment, I have grasped how to convert from case classes to HList via Generic or LabelledGeneric. The problem is once I have this conversion done how I can call the methods fromXmlrpc and toXmlrpc as in the asProduct2 example. I don't have any information about the types of the attributes in the case class and, therefore, the compiler cannot find any implicit that satisfy fromXmlrpc and toXmlrpc. I need a way to constrain that all the elements of a HList have an implicit Datatype in context.
As I am a beginner with Shapeless, I would like to know what's the best way of getting this functionality. I have some insights but I definitely have no idea of how to get it done using Shapeless. The ideal would be to have a way to get the type from a given attribute of the case class and pass this type explicitly to fromXmlrpc and toXmlrpc. I imagine that this is not how it can be done.
First, you need to write generic serializers for HList. That is, you need to specify how to serialize H :: T and HNil:
implicit def hconsDatatype[H, T <: HList](implicit hd: Datatype[H],
td: Datatype[T]): Datatype[H :: T] =
new Datatype[H :: T] {
override def serialize(value: H :: T): NodeSeq = value match {
case h :: t =>
val sh = hd.serialize(h)
val st = td.serialize(t)
(sh ++ st).theSeq
}
override def deserialize(from: NodeSeq): Deserialized[H :: T] =
(hd.deserialize(from.head) |#| td.deserialize(from.tail)) {
(h, t) => h :: t
}
}
implicit val hnilDatatype: Datatype[HNil] =
new Datatype[HNil] {
override def serialize(value: HNil): NodeSeq = NodeSeq()
override def deserialize(from: NodeSeq): Deserialized[HNil] =
Success(HNil)
}
Then you can define a generic serializer for any type which can be deconstructed via Generic:
implicit def genericDatatype[T, R](implicit gen: Generic.Aux[T, R],
rd: Lazy[Datatype[R]]): Datatype[T] =
new Datatype[T] {
override def serialize(value: T): NodeSeq =
rd.value.serialize(gen.to(value))
override def deserialize(from: NodeSeq): Deserialized[T] =
rd.value.deserialize(from).map(rd.from)
}
Note that I had to use Lazy because otherwise this code would break the implicit resolution process if you have nested case classes. If you get "diverging implicit expansion" errors, you could try adding Lazy to implicit parameters in hconsDatatype and hnilDatatype as well.
This works because Generic.Aux[T, R] links the arbitrary product-like type T and a HList type R. For example, for this case class
case class A(x: Int, y: String)
shapeless will generate a Generic instance of type
Generic.Aux[A, Int :: String :: HNil]
Consequently, you can delegate the serialization to recursively defined Datatypes for HList, converting the data to HList with Generic first. Deserialization works similarly but in reverse - first the serialized form is read to HList and then this HList is converted to the actual data with Generic.
It is possible that I made several mistakes in the usage of NodeSeq API above but I guess it conveys the general idea.
If you want to use LabelledGeneric, the code would become slightly more complex, and even more so if you want to handle sealed trait hierarchies which are represented with Coproducts.
I'm using shapeless to provide generic serialization mechanism in my library, picopickle. I'm not aware of any other library which does this with shapeless. You can try and find some examples how shapeless could be used in this library, but the code there is somewhat complex. There is also an example among shapeless examples, namely S-expressions.
Vladimir's answer is great and should be the accepted one, but it's also possible to do this a little more nicely with Shapeless's TypeClass machinery. Given the following setup:
import scala.xml.NodeSeq
import scalaz._, Scalaz._
trait Serializer[T] {
def serialize(value: T): NodeSeq
}
trait Deserializer[T] {
type Deserialized[T] = Validation[AnyErrors, T]
type AnyError = Throwable
type AnyErrors = NonEmptyList[AnyError]
def deserialize(from: NodeSeq): Deserialized[T]
}
trait Datatype[T] extends Serializer[T] with Deserializer[T]
We can write this:
import shapeless._
object Datatype extends ProductTypeClassCompanion[Datatype] {
object typeClass extends ProductTypeClass[Datatype] {
def emptyProduct: Datatype[HNil] = new Datatype[HNil] {
def serialize(value: HNil): NodeSeq = Nil
def deserialize(from: NodeSeq): Deserialized[HNil] = HNil.successNel
}
def product[H, T <: HList](
dh: Datatype[H],
dt: Datatype[T]
): Datatype[H :: T] = new Datatype[H :: T] {
def serialize(value: H :: T): NodeSeq =
dh.serialize(value.head) ++ dt.serialize(value.tail)
def deserialize(from: NodeSeq): Deserialized[H :: T] =
(dh.deserialize(from.head) |#| dt.deserialize(from.tail))(_ :: _)
}
def project[F, G](
instance: => Datatype[G],
to: F => G,
from: G => F
): Datatype[F] = new Datatype[F] {
def serialize(value: F): NodeSeq = instance.serialize(to(value))
def deserialize(nodes: NodeSeq): Deserialized[F] =
instance.deserialize(nodes).map(from)
}
}
}
Be sure to define these all together so they'll be properly companioned.
Then if we have a case class:
case class Foo(bar: String, baz: String)
And instances for the types of the case class members (in this case just String):
implicit object DatatypeString extends Datatype[String] {
def serialize(value: String) = <s>{value}</s>
def deserialize(from: NodeSeq) = from match {
case <s>{value}</s> => value.text.successNel
case _ => new RuntimeException("Bad string XML").failureNel
}
}
We automatically get a derived instance for Foo:
scala> case class Foo(bar: String, baz: String)
defined class Foo
scala> val fooDatatype = implicitly[Datatype[Foo]]
fooDatatype: Datatype[Foo] = Datatype$typeClass$$anon$3#2e84026b
scala> val xml = fooDatatype.serialize(Foo("AAA", "zzz"))
xml: scala.xml.NodeSeq = NodeSeq(<s>AAA</s>, <s>zzz</s>)
scala> fooDatatype.deserialize(xml)
res1: fooDatatype.Deserialized[Foo] = Success(Foo(AAA,zzz))
This works about the same as Vladimir's solution, but it lets Shapeless abstract some of the boring boilerplate of type class instance derivation so you don't have to get your hands dirty with Generic.
According to the scala specification, the extractor built by case classes is the following (scala specification ยง5.3.2):
def unapply[tps](x: c[tps]) =
if (x eq null) scala.None
else scala.Some(x.xs11, ..., x.xs1k)
For implementation reasons, I want to be able to mimic the behavior of this extractor on a non-case class.
However, my implementation fails to reproduce the same behavior.
Here is an example of the difference i have:
trait A
sealed trait B[X <: A]{ val x: X }
case class C[X <: A](x: X) extends B[X]
class D[X <: A](val x: X) extends B[X]
object D {
def unapply[X <: A](d: D[X]): Option[X] =
if (d eq None) None
else Some(d.x)
}
def ext[X <: A](b: B[X]) = b match {
case C(x) => Some(x)
case D(x) => Some(x)
case _ => None
}
I have the following warning :
<console>:37: warning: non variable type-argument X in type pattern D[X] is unchecked since it is eliminated by erasure
case D(x) => Some(x)
Notice the warning occurs only in the D case, not in the case-class textractor case.
Do you have any idea about the cause of the warning / about what I should do to avoid this warning ?
Note: If you want to test it in REPL, the easiest way is:
To activate unchecked warning
scala> :power
scala> settings.unchecked.value = true
To copy above code in paste mode:
scala> :paste
[copy/paste]
[ctrl + D]
Edit: As Antoras mentioned it should be a compiler bug, maybe the scala version could be useful: scala 2.9.0.1
(after a quick test, still there in scala 2.9.1RC2)
This seems to be a compiler bug. I have analyzed the output of the compiler AST (with fsc -Xprint:typer <name_of_file>.scala). It interprets both as the same:
...
final <synthetic> object C extends java.lang.Object with ScalaObject with Serializable {
def this(): object test.Test.C = {
C.super.this();
()
};
final override def toString(): java.lang.String = "C";
case <synthetic> def unapply[X >: Nothing <: test.Test.A](x$0: test.Test.C[X]): Option[X] = if (x$0.==(null))
scala.this.None
else
scala.Some.apply[X](x$0.x);
case <synthetic> def apply[X >: Nothing <: test.Test.A](x: X): test.Test.C[X] = new test.Test.C[X](x);
protected def readResolve(): java.lang.Object = Test.this.C
};
...
final object D extends java.lang.Object with ScalaObject {
def this(): object test.Test.D = {
D.super.this();
()
};
def unapply[X >: Nothing <: test.Test.A](d: test.Test.D[X]): Option[X] = if (d.eq(null))
scala.None
else
scala.Some.apply[X](d.x)
};
...
The method signature of both methods unapply are identical.
Furthermore the code works fine (as expected due to identical methods):
trait A {
def m = "hello"
}
class AA extends A
sealed trait B[X <: A]{ val x: X }
case class C[X <: A](x: X) extends B[X]
class D[X <: A](val x: X) extends B[X]
object D {
def apply[X <: A](x: X) = new D(x)
def unapply[X <: A](d: D[X]): Option[X] =
if (d eq null) None
else Some(d.x)
}
def ext[X <: A](b: B[X]) = b match {
case C(x) => Some("c:"+x.m)
case D(x) => Some("d:"+x.m)
case _ => None
}
println(ext(C[AA](new AA())))
println(ext(D[AA](new AA())))
The following code, which is taken from Apocalisp's excellent blog series:
Type level programming in scala , and modified for an implicit parsing scenario. However, this does not compile, with the following message:
error: ambiguous implicit values:
both method hParseNil in object HApplyOps of type => (com.mystuff.bigdata.commons.collections.hlist.HNil) => com.mystuff.bigdata.commons.collections.hlist.HNil
and method conforms in object Predef of type [A]<:<[A,A]
match expected type (com.mystuff.bigdata.commons.collections.hlist.HNil) => com.amadesa.bigdata.commons.collections.hlist.HNil
val l = hparse[HNil,HNil](HNil)
Can someone please explain why this happens, and if it's fixable?
sealed trait HList
final case class HCons[H, T <: HList](head: H, tail: T) extends HList {
def :+:[T](v: T) = HCons(v, this)
}
sealed class HNil extends HList {
def :+:[T](v: T) = HCons(v, this)
}
object HNil extends HNil
// aliases for building HList types and for pattern matching
object HList {
type :+:[H, T <: HList] = HCons[H, T]
val :+: = HCons
}
object HApplyOps
{
import HList.:+:
implicit def hParseNil: HNil => HNil = _ => HNil
implicit def hParseCons[InH,OutH,TIn <:HList,TOut<:HList](implicit parse:InH=>OutH,parseTail:TIn=>TOut): (InH :+: TIn) => (OutH :+: TOut) =
in => HCons(parse(in.head),parseTail(in.tail))
def hparse[In <: HList, Out <: HList](in:In)(implicit parse: In => Out):Out = in
}
object PG {
import HList._
def main(args: Array[String]) {
import HApplyOps._
val l = hparse[HNil,HNil](HNil)
}
}
Although i can't tell you exactly the purpose of Predef.conforms, i can tell you the ambiguity error seems correct (unfortunately). In the comment in the source it even says that <:< was introduced because of ambiguity problems of Function1 (says Function2 but i guess that is a mistake). But since <:< is a subclass of Function1 it can be passed in whenever Function1 is expected, so in your case its possible to pass in <:< to hparse.
Now the implicit def conforms[A]: A <:< A has the effect (from what i understand) that whenever a method expects a type A => A, it is sufficient to have an implicit value of A in scope.
In your case the implicit def hParseNil: HNil => HNil has the same priority as conforms and thus both could be equally applied.
I see two possible solutions:
just remove the hParseNil, i think your code still works.
shadow the Predef's conforms by naming yours the same:
implicit def conforms: HNil => HNil = _ => new HNil
You can just replace the function literal hParseNil to a normal function.
implicit def hParseNil(a:HNil): HNil = HNil
instead of
implicit def hParseNil: HNil => HNil = _ => HNil