I am using scalacheck and am in the middle of a generic-programming soup right now. The official guide shows this example:
def matrix[T](g: Gen[T]): Gen[Seq[Seq[T]]] = Gen.sized { size =>
val side = scala.math.sqrt(size).asInstanceOf[Int]
Gen.listOfN(side, Gen.listOfN(side, g))
}
Meanwhile, for my test I require a matrix of type Array[Array[T]]. I tried with the following function:
def matrix[T](g: Gen[T]): Gen[Array[Array[T]]] = Gen.sized { size =>
val side = scala.math.sqrt(size).asInstanceOf[Int]
val g1 = Gen.containerOfN[Array, T](side, g)
Gen.containerOfN[Array, Array[T]](side, g1)
}
Here, I run into trouble. The compiler says:
Multiple markers at this line
- not enough arguments for method containerOfN: (implicit b: org.scalacheck.util.Buildable[T,Array])org.scalacheck.Gen[Array[T]].
Unspecified value parameter b.
- could not find implicit value for parameter b: org.scalacheck.util.Buildable[T,Array]
- could not find implicit value for parameter b: org.scalacheck.util.Buildable[T,Array]
- not enough arguments for method containerOfN: (implicit b: org.scalacheck.util.Buildable[T,Array])org.scalacheck.Gen[Array[T]].
Unspecified value parameter b.
I understand that stuff like this is usually remedied by adding implicit parameters to the function, however, i havent made this work yet.
I usually encounter this error when building generic arrays, as an example:
def build[T](n:Int)(implicit m:ClassManifest[T]) = Array.ofDim[T](n)
but, I am afraid I don't fully understand what is happening or why this is needed.
Can someone explain how to make the correct matrix-function along with an example of usage in scalacheck? A thorough explanation of the details about building sequences with implicit class manifests would be very welcome!
edit
import org.scalacheck.util.Buildable._
def matrix[T](g: Gen[T])(implicit b: Buildable[T, Array]): Gen[Array[Array[T]]] = Gen.sized { size =>
val side = scala.math.sqrt(size).asInstanceOf[Int]
val g1 = Gen.containerOfN[Array, T](side, g)
Gen.containerOfN[Array, Array[T]](side, g1)
}
Still doesn't work. Need implicit for Buildable[Array[T],Array]... Don't know how to get this because I can only add 1 implicit argument :/
You're almost there. The important part of the error is could not find implicit value for parameter b: org.scalacheck.util.Buildable[T,Array]
Looking at the method definition of containerOfN
def containerOfN[C[_],T](n: Int, g: Gen[T])(implicit b: Buildable[T,C]): Gen[C[T]] = ...
So, there's your missing argument. You need an implicit argument of type Buildable[T,Array]. Following through to where Buildable is defined in the scalacheck sources, I found that there was an object (org.scalacheck.util.Buildable) that provides implicits that provide Buildables for the common collection types which includes Array. So all you need to bring that into scope. You can do this with:
import org.scalacheck.util.Buildable._
def matrix[T](g: Gen[T]): Gen[Array[Array[T]]] = Gen.sized { size =>
val bT = implicitly[Buildable[T, Array]]
val bArrayT = implicitly[Buildable[Array[T], Array]]
val side = scala.math.sqrt(size).asInstanceOf[Int]
val g1 = Gen.containerOfN[Array, T](side, g)
Gen.containerOfN[Array, Array[T]](side, g1)
}
Or
import org.scalacheck.util.Buildable._
def matrix[T](g: Gen[T])(implicit bT: Buildable[T, Array], bArrayT: Buildable[Array[T], Array]): Gen[Array[Array[T]]] = Gen.sized { size =>
...
}
The particular implicit you need in org.scalacheck.util.Buildable is:
implicit def buildableArray[T](implicit cm: ClassManifest[T]) =
new Buildable[T,Array] {
def builder = mutable.ArrayBuilder.make[T]
}
Related
I am getting an error in the extractor step (unapply method call).
The error message is: Wrong number of arguments for the extractors. found 2; expected 0
Can someone please help what is causing the error (where my misunderstanding is).
class ABC(val name:String, val age:Int) //class is defined.
object ABC{
def apply(age:Int, name:String) = new ABC(name, age)
def unapply(x:ABC) = (x.name, x.age)
}
val ins = ABC(25, "Joe") //here apply method is in action.
val ABC(x,y) = ins //unapply is indirectly called. As per my understanding , 25 and Joe suppose to be captured in x and y respectively. But this steps gives error.
The error I get is
an unapply result must have a member def isEmpty: Boolean
The easiest way to fix this is to make unapply return an Option:
def unapply(x: ABC) = Option((x.name, x.age))
The unapply method in an extractor which binds values must return an Option. This is because there's no intrinsic guarantee that an extractor will always succeed. For instance consider this massively oversimplified example of an extractor for an email address:
object Email {
def unapply(s: String): Option[(String, String)] =
s.indexOf('#') match {
case idx if idx >= 0 =>
val (user, maybeSite) = s.splitAt(idx)
if (maybeSite.length < 2 || maybeSite.lastIndexOf('#') > 0) None
else Some(user -> maybeSite.tail)
case _ => None
}
}
At the application site:
val Email(u, s) = "user3103957#stackoverflow.example.xyz"
Turns into code that's basically (from the description in Programming In Scala (Odersky, Spoon, Venners (3rd ed))):
val _tmpTuple2 =
"user3103957#stackoverflow.example.xyz" match {
case str: String =>
Email.unapply(str).getOrElse(throw ???)
case _ => throw ???
}
val u = _tmpTuple2._1
val s = _tmpTuple2._2
Technically, since the compiler already knows that the value is a String, the type check is elided, but I've included the type check for generality. The desugaring of extractors in a pattern match also need not throw except for the last extractor attempt.
I would like to understand how I should compose Kleislis that return "complex" types (e.g. F[Either[A,B]]). Here's an example of what I mean:
This is a simple case - given two Kleislis
val parseRegistration: Kleisli[Result, Auth.Registration, Auth.Registration] = ???
val hashPassword: Kleisli[Result, Auth.Registration, Auth.Registration] = ???
I can compose them in this way:
val validateAndHash = parseRegistration andThen hashPassword
And all is fine.
However, given more complex Kleisli types (where the return value is an Either[A, B]), I'm not able to compose them directly (because I ended up with F[Either[A,B]] where a Kleisli expects only F[A]).
// relevant type definitions
final case class ServiceError(kind: ErrorKind, message: String = "", cause: Option[Throwable] = None)
final type Result[A] = Either[ServiceError, A]
final case class Registration(email: String, password: String)
final case class Registered(session: Session)
val createUser: Kleisli[F, Auth.Registration, Result[Long]] = ???
val createSession: Kleisli[F, Long, Result[Session]] = ???
// does not compile (no overloaded alternatives match the arguments) - I expected this as
// createUser returns F[Result[Long]] and the createSession Kleisli expects only F[Long]
val createUserAndSession = createUser andThen createSession
Ok, so as expected. Then, instead of composing them, I tried simply performing nested maps:
val r1 = validateAndHash(info) // Result[Auth.Registration]
val r2 = r1.map(i => createUser(i)) // Either[ServiceError, F[Result[Long]]]
val r3 = r2.map(_.map(_.map(uid => createSession(uid).map(_.map(Auth.Registered.apply)))))
// Now I've got an Either[ServiceError, F[Either[ServiceError, F[Either[ServiceError, Auth.Registered]]]]]
// in r3! I wanted to end up with F[Result[Auth.Registered]]
So I've ended up causing increasing nesting and flatten doesn't seem to help because F and Result can't be flattened into each other.
I'm sure this is something the seasoned scala cats programmers encounter all the time, so I'd appreciate it if you could help me understand how I can avoid getting myself into this mess?
EDIT:
I have now defined a function to invert the nested wrapper types so they can then be flattened:
def invert[S, F[_]: Monad, V](e: Either[S, F[V]]): F[Either[S, V]] =
e match {
case Left(s) => Monad[F].pure(Left(s))
case Right(fv) => fv.map(Right(_))
}
This allows me to do this:
val r1 = validateAndHash(info)
val r2 = invert(r1.map(i => createUser(i))).map(_.flatten)
val r3 = r2.map( i => invert(i.map(uid => createSession(uid).map(_.map(Auth.Registered.apply)))).map(_.flatten))
val r4 = Monad[F].flatten(r3)
Which seems... clumsy? And too specific to Either. Is there a cleaner way to do this using something built in to cats?
I would rather compose values than play with Kleisli, especially since EitherT makes this pretty simple.
First, let's refactor createUser & createSession to be normal methods:
def createUser[F[_]](registration: Registration): F[Result[Long]] = ???
def createSession[F[_]](long: Long): F[Result[Session]] = ???
And now let's implement createUserAndSession
import cats.Monad
import cats.data.EitherT
def createUserAndSession[F[_]](registration: Registration)(implicit ev: Monad[F]): F[Result[Session]] =
EitherT(createUser(registration)).flatMapF(createSession).value
I am writing a compiler plugin to rewrite a function definition as a tuple of the function hash + function body
So the following
def f(a: Int, b: Int) : Int = (a + b)
would turn into
val f = ("some-complex-hash", (a: Int, b: Int) => (a + b))
Let me note that, this is for a research project and will be used to integrate some variant of reversible computations into a subset of the language. I am aware that, on its own, this is a bad idea and will break a lot of things.
The documentation of compiler plug in construction seems to be rather lacking (I did go through the official guide), so I am trying to make progress looking at existing plugins such as the kind-projector
In order to understand how to represent this, I have followed the following process
Reify the expression val expr = reify {....}
Extract the tree val tree = expr.tree
showRaw(tree)
I have done this for a function definition, tuple and a lambda, which I believe should be enough to implement this. I got the following so far:
ValDef(Modifiers(), TermName(dd.name), TypeTree(),
Apply(
Select(Ident("scala.Tuple2"), TermName("apply")),
List(
Literal(Constant(hash)),
Function(
List(dd.vparamss),
dd.rhs
)
)
)
)
Before I even get to this, I am having trouble with expanding to any tuple at all i.e. rewrite any function as ("a", "b") which expands to the following in the REPL
Apply(Select(Ident(scala.Tuple2), TermName("apply")), List(Literal(Constant("a")), Literal(Constant("b"))))
The Problem
If I do Ident(scala.Tuple2) I get the following at compile time
overloaded method value Ident with alternatives:
[error] (sym: FunctionRewriter.this.global.Symbol)FunctionRewriter.this.global.Ident <and>
[error] (name: String)FunctionRewriter.this.global.Ident <and>
[error] FunctionRewriter.this.global.Ident.type
[error] cannot be applied to (Tuple2.type)
[error] Select(Ident(scala.Tuple2), TermName("apply")),
If I do Ident("scala.Tuple2") (notice the string), I get the following when the plug in runs (at "run time")
<test>:2: error: not found: value scala.Tuple2
[error] object Main extends App {
I would appreciate any pointers on how to rewrite as Tuples
The Full Code:
class CompilerPlugin(override val global: Global) extends Plugin {
val name = "provenance-expander"
val components = new FunctionRewriter(global) :: Nil
}
class FunctionRewriter(val global: Global) extends PluginComponent with TypingTransformers {
import global._
override val phaseName = "compiler-plugin-phase"
override val runsAfter = List("parser")
override def newPhase(prev: Phase) = new StdPhase(prev) {
override def apply(unit: CompilationUnit) {
unit.body = new MyTypingTransformer(unit).transform(unit.body)
}
}
class MyTypingTransformer(unit: CompilationUnit) extends TypingTransformer(unit) {
override def transform(tree: Tree) : Tree = tree match {
case dd: DefDef =>
val hash: String = "do some complex recursive hashing"
Apply(
Select(Ident("scala.Tuple2"), TermName("apply")),
List(Literal(Constant("a")), Literal(Constant("b")))
)
case _ => super.transform(tree)
}
}
def newTransformer(unit: CompilationUnit) = new MyTypingTransformer(unit)
}
Thanks to #SethTisue for answering in the comments. I am writing up a answer for anybody who might face a similar issue in the future.
As Seth mentioned, using mkTuple was the right way to go. In order to use it, you need the following import
import global.gen._
In this specific case, as originally speculated in the question, the transformation breaks a lot of things. Mainly transforming the methods injected by object and class definitions i.e. for method dispatch or init, results in malformed structures. The work around is using explicit annotations. So the final DefDef ends up looking like the following:
case dd: DefDef =>
if (dd.mods.hasAnnotationNamed(TypeName(typeOf[policyFunction].typeSymbol.name.toString))) {
val hash: String = md5HashString(dd.rhs.toString())
val tup =
atPos(tree.pos.makeTransparent)(mkTuple(List(Literal(Constant(hash)), Function(dd.vparamss(0), dd.rhs))))
val q = ValDef(Modifiers(), dd.name, TypeTree(), tup)
println(s"Re-written Function: $q")
q
} else {
dd
}
I am trying to write the following implicit:
implicit class ExtractOrElse[K, V](o: Option[Map[K, V]]) {
def extractOrElse(key: K)(f: => V): V = { if (o.isDefined) o.get(key) else f }
}
Which I want to use in this way:
normalizationContexts.extractOrElse(shardId)(defaultNormalizationContext)
to avoid a clunkier syntax (normalizationContexts is an Option[Map[String, NormzalitionContext]]).
Also, let me add that it is intentional that there is only one default value: it will be used if the Option isEmpty, but if the Option isDefined, then the behavior of the Map is not changed, and it will throw an exception if the key is not found - so the default value won't be used in that case, and this is all intentional.
However, I get an error when passing in None in unit tests:
assertEquals(None.extractOrElse('a')(0), 0)
results in:
Error:(165, 37) type mismatch;
found : Char('a')
required: K
assertEquals(None.extractOrElse('a')(0), 0)
I realize that None is not parametric, as it is defined as:
case object None extends Option[Nothing] {
def isEmpty = true
def get = throw new NoSuchElementException("None.get")
What is the best way to make this work?
Instead of None.extractOrElse(...), try Option.empty[Map[Char, Int]].extractOrElse(...).
If you always use the same types for your test cases, you could also create a type alias in the specs class in order to reduce the clutter:
type OpMap = Option[Map[Char, Int]]
// ...
assertEquals(Option.empty[OpMap].extractOrElse('a')(0), 0)
Just in case, you can use flatMap and getOrElse to achieve the same thing without writing a new method:
val n = Option.empty[Map[String, Int]]
val s = Some(Map("x" → 1, "y" → 2))
n.flatMap(_.get("x")).getOrElse(3) // 3
s.flatMap(_.get("x")).getOrElse(3) // 1
s.flatMap(_.get("z")).getOrElse(3) // 3
The type system doesn't have enough information about the types K and V. There is no way to know what the type of A would be in the case where your None was Some[A].
When I create an example with explicit types, the code works as expected:
// Like this
val e = new ExtractOrElse(Option.empty[Map[Char, Int]])
e.extractOrElse('a')(0) // Equals 0
// Or like this
val e = new ExtractOrElse[Char, Int](None)
println(e.extractOrElse('a')(0))
// Or like this
val m: Option[Map[Char, Int]] = None
val e = new ExtractOrElse(m)
println(e.extractOrElse('a')(0))
I am still in a process of figuring out the exact typing rules/implications involved in here.
It seems easy/easier if the types in the examples are "simple enough" to "fit well" as in almost all simple examples is the case, but it becomes more interresting/difficult (at least for me) in comparing things to the typing given by tiark rompf:
|- e: A#cpsParam[B,C]; {[|r|]}: U
-----------------------------------------------------
[|val x: A = e; r|] = [|e|].map( (x: A) => {[|r|]} )
so the result of [|e|].map( (x: A) => {[|r|]} ) will have the type Shift[U,B,C] according to the definition of map given in tiark's paper.
Here U is not necessarily the same as B.
So far I do not understand why U is allowed to be different from B without something like U <: B given in the definition of map in tiark's paper.
What am I missing respectively failing to understand here?
Any tips/ideas?
I had a second look at this as wanted to see what the result of the selective cps transform will yield in both cases.
U <: B
U is not a subtype of B
I used the following simple example:
package sample
import scala.util.continuations._
class Depp {
override def toString = "DEPP"
}
class Sepp extends Depp {
override def toString = "DEPP->SEPP"
}
object Sample extends Application {
val depp = new Depp
val sepp = new Sepp
val res = reset {
shift {
(k: Int => Depp) => k(7)
}
val z = sepp
z
}
println("Result = "+ res)
}
Compiling this using
scalac -P:continuations:enable -Xprint:selectivecps Sample.scala
proves successful and yields the following (interesting part only):
private[this] val res: sample.Depp = scala.util.continuations.package.reset[sample.Sepp, sample.Depp]({
package.this.shiftR[Int, sample.Depp, sample.Depp](((k: (Int) => sample.Depp) => k.apply(7))).map[sample.Sepp]
tmp1;
val z: sample.Sepp = Sample.this.sepp;
z
}))
ok so the type of the resulting (application of map) Shift object is [Sepp,Depp,Depp] as expected :)
which is fine because i understand how Shift objects like A#cpsParam[A,C] come into existence (the reset function given in Tiark's paper operates on such Shift objects)
Now changing the following in the simple example to yield a type unrelated to Depp: z.asInstanceOf[Float]
compiling this with
scalac -P:continuations:enable -Xprint:selectivecps -explaintypes Sample.scala
brings up the following error which tells what is actually checked:
Sample.scala:16: error: type mismatch;
found : Float #scala.util.continuations.cpsParam[sample.Depp,sample.Depp] #scala.util.continuations.cpsSynth
required: Float #scala.util.continuations.cpsParam[Float,sample.Depp]
val res = reset {
^
Float #scala.util.continuations.cpsParam[sample.Depp,sample.Depp] #scala.util.continuations.cpsSynth <: Float #scala.util.continuations.cpsParam[Float,sample.Depp]?
scala.util.continuations.cpsParam[sample.Depp,sample.Depp] <: scala.util.continuations.cpsParam[Float,sample.Depp]?
Float <: sample.Depp?
<notype> <: sample.Depp?
false
false
false
false
one error found
ahh and here is the test: Float <: sample.Depp?
so it fails because Float of course isn't a subtype of Depp
question: shouldn't the transformation rule then better be given as:
e: A#cpsParam[B,C] {[|r|]}: U U <: B
-----------------------------------------------------
[|val x: A = e; r|] = [|e|].map( (x: A) => {[|r|]} )
to clearly express this?