Scala recursive parameters? - scala

Could you please tell me what is wrong with this Scala code?
package com.user.common
class Notification(message: String, next: Option[Notification]) {
def write(): String = {
message
}
def getAll(): Stream[Notification] = {
next match {
case Some(n) => Stream.cons(n, n.getAll())
case None => Stream.empty
}
}
}
case class Email(msg: String)
extends Notification(msg, None)
case class SMS(msg: String)
extends Notification(msg, Option(Email))
case class VoiceRecording(msg: String)
extends Notification(msg, Option(SMS))
The errors from compiler are as below.
[error] /common/Test.scala:15: type mismatch;
[error] found : Some[A]
[error] required: Option[com.user.common.Notification]
[error] case Some(n) => Stream.cons(n, n.getAll())
[error] ^
[error] /common/Test.scala:15: type mismatch;
[error] found : A
[error] required: com.user.common.Notification
[error] case Some(n) => Stream.cons(n, n.getAll())
[error] ^
[error] /common/Test.scala:15: value getAll is not a member of type parameter A
[error] case Some(n) => Stream.cons(n, n.getAll())
[error] ^
[error] /common/Test.scala:25: type mismatch;
[error] found : com.user.common.Email.type
[error] required: com.user.common.Notification
[error] extends Notification(msg, Option(Email))
[error] ^
[error] /common/Test.scala:28: type mismatch;
[error] found : com.user.common.SMS.type
[error] required: com.user.common.Notification
[error] extends Notification(msg, Option(SMS))
[error] ^
[error] 5 errors found
[error] (compile:compileIncremental) Compilation failed
I could not understand the problem. Similarly, I have no idea how to restructure the code. My basic idea is to keep value of one case class and iterate over them until I reach to None. From top level case class until low level one.

case class SMS(msg: String)
extends Notification(msg, Option(Email))
case class VoiceRecording(msg: String)
extends Notification(msg, Option(SMS))`
In your second parameter, you are passing an option on a class type whereas an instance of the class is expected
Maybe what you want is
case class SMS(msg: String)
extends Notification(msg, Option(Email(msg)))
case class VoiceRecording(msg: String)
extends Notification(msg, Option(SMS(msg)))`

Related

Using Cats Show on enum

I need to implement the cats Show instances for an enum which express the basic operators.
enum Expr[T]:
case Plus(left: Expr[Double], right: Expr[Double]) extends Expr[Double]
case Minus(left: Expr[Double], right: Expr[Double]) extends Expr[Double]
case Num(value: Double) extends Expr[Double]
object Expr {
def eval[T](expr: Expr[T]): T =
expr match {
case Plus(left, right) => eval(left) + eval(right)
case Minus(left, right) => eval(left) - eval(right)
case Num(value) => value
}
After reading the doc, I tried to implement as following:
object ExprShow {
implicit val numShow: Show[Expr.Num] = Show.show(
num => num.value.toString
)
implicit val minusShow: Show[Expr.Minus] = Show.show(
minus => show"${minus.left} - ${minus.right}"
)
implicit val plusShow: Show[Expr.Plus] = Show.show(
plus => show"${plus.left} + ${plus.right}"
)
}
But I got the errors when trying to execute the show method:
val test = Expr.Num(3.0)
test.show
[error] -- [E007] Type Mismatch Error:
[error] 69 | minus => show"${minus.left} - ${minus.right}"
[error] | ^^^^^^^^^^
[error] | Found: (minus.left : grox.Expr[Double])
[error] | Required: cats.Show.Shown
[error] Explanation
[error] ===========
[error]
[error] Tree: minus.left
[error]
[error] I tried to show that
[error] (minus.left : grox.Expr[Double])
[error] conforms to
[error] cats.Show.Shown
[error] but the comparison trace ended with `false`:
[error]
[error] ==> (minus.left : grox.Expr[Double]) <: cats.Show.Shown
[error] ==> (minus.left : grox.Expr[Double]) <: cats.Show.Shown (recurring)
[error] ==> grox.Expr[Double] <: cats.Show.Shown (left is approximated)
[error] ==> grox.Expr[Double] <: cats.Show.Shown (recurring)
[error] <== grox.Expr[Double] <: cats.Show.Shown (recurring) = false
[error] <== grox.Expr[Double] <: cats.Show.Shown (left is approximated) = false
[error] <== (minus.left : grox.Expr[Double]) <: cats.Show.Shown (recurring) = false
[error] <== (minus.left : grox.Expr[Double]) <: cats.Show.Shown = false
[error]
[error] The tests were made under a constraint with:
[error] uninstantiated variables: A
[error] constrained types: [A](f: A => String): cats.Show[A],
[error] [A](f: A => String): cats.Show[A]
...
----------
[error] -- [E008] Not Found Error:
[error] 15 | test.show
[error] | ^^^^^^^^^
[error] | value show is not a member of grox.Expr[Double]
Is there any best practice approach to implement cats Show for enum? What's the root cause of my issue? Any suggestions or doc recommendation would be appreciated. Thanks a bunch
implicit val minusShow: Show[Expr.Minus] = Show.show(
minus => show"${minus.left} - ${minus.right}"
)
minus.left type is Expr[Double], you should define Show[Expr[Double]] first so it could find the correct implicit.
Here is the solution
implicit def exprShow[T]: Show[Expr[T]] = Show.show(
num => Expr.eval(num).toString
)

Encountering errors when trying to write either a Circe encoder or decoder for ADT

I'm trying to write some code based on Circe's documentation, however, trying to compile both my encoder and decoder results in an error.
If you would like to take a look at the entire project, you can do so on github (link to the file I have issues with)
The Decoder
Trying to compile the below code:
package model
import java.time.LocalDateTime
import cats.effect.IO
import cats.syntax.functor._
import io.circe.generic.auto._
import io.circe.syntax._
import io.circe.{Decoder, Encoder}
import org.http4s.EntityDecoder
import org.http4s.circe.jsonOf
package object account {
sealed trait AccountStatus
case object Onboarding extends AccountStatus
case object SubmissionFailed extends AccountStatus
case object Submitted extends AccountStatus
case object AccountUpdated extends AccountStatus
case object ApprovalPending extends AccountStatus
case object Active extends AccountStatus
case object Rejected extends AccountStatus
object AccountStatus {
implicit val accountStatusEncoder: Encoder[AccountStatus] = Encoder.instance {
case onboarding#Onboarding => onboarding.asJson
case submissionFailed#SubmissionFailed => submissionFailed.asJson
case submitted#Submitted => submitted.asJson
case accountUpdated#AccountUpdated => accountUpdated.asJson
case approvalPending#ApprovalPending => approvalPending.asJson
case active#Active => active.asJson
case rejected#Rejected => rejected.asJson
}
implicit val accountStatusDecoder: Decoder[AccountStatus] =
List[Decoder[AccountStatus]](
Decoder[Onboarding].widen,
Decoder[SubmissionFailed].widen,
Decoder[Submitted].widen,
Decoder[AccountUpdated].widen,
Decoder[ApprovalPending].widen,
Decoder[Active].widen,
Decoder[Rejected].widen
).reduceLeft(_ or _)
implicit val AccountStatusEntityDecoder = jsonOf[IO, AccountStatus]
}
case class Account(
id: String,
status: AccountStatus,
currency: String,
buyingPower: Double,
cash: Double,
cashWithdrawable: Double,
portfolioValue: Double,
patternDayTrader: Boolean,
tradingBlocked: Boolean,
transfersBlocked: Boolean,
accountBlocked: Boolean,
createdAt: LocalDateTime
)
object Account {
implicit val AccountDecoder: EntityDecoder[IO, Account] = jsonOf[IO, Account]
}
}
results in the following errors:
[error] /home/tom/code/scalpaca/src/main/scala/model/account.scala:38:19: not found: type Onboarding
[error] Decoder[Onboarding].widen,
[error] ^
[error] /home/tom/code/scalpaca/src/main/scala/model/account.scala:39:19: not found: type SubmissionFailed
[error] Decoder[SubmissionFailed].widen,
[error] ^
[error] /home/tom/code/scalpaca/src/main/scala/model/account.scala:40:19: not found: type Submitted
[error] Decoder[Submitted].widen,
[error] ^
[error] /home/tom/code/scalpaca/src/main/scala/model/account.scala:41:19: not found: type AccountUpdated
[error] Decoder[AccountUpdated].widen,
[error] ^
[error] /home/tom/code/scalpaca/src/main/scala/model/account.scala:42:19: not found: type ApprovalPending
[error] Decoder[ApprovalPending].widen,
[error] ^
[error] /home/tom/code/scalpaca/src/main/scala/model/account.scala:43:19: not found: type Active
[error] Decoder[Active].widen,
[error] ^
[error] /home/tom/code/scalpaca/src/main/scala/model/account.scala:44:19: not found: type Rejected
[error] Decoder[Rejected].widen
[error] ^
[error] 7 errors found
I find this rather confusing as the types the compiler complains about are quite clearly in scope, at least as far as I can tell.
The Encoder
Removing the decoder, the AccountStatusEntityDecoder that depends on it and the AccountStatus field from account, being left with the below
package model
import java.time.LocalDateTime
import cats.effect.IO
import cats.syntax.functor._
import io.circe.generic.auto._
import io.circe.syntax._
import io.circe.{Decoder, Encoder}
import org.http4s.EntityDecoder
import org.http4s.circe.jsonOf
package object account {
sealed trait AccountStatus
case object Onboarding extends AccountStatus
case object SubmissionFailed extends AccountStatus
case object Submitted extends AccountStatus
case object AccountUpdated extends AccountStatus
case object ApprovalPending extends AccountStatus
case object Active extends AccountStatus
case object Rejected extends AccountStatus
object AccountStatus {
implicit val accountStatusEncoder: Encoder[AccountStatus] = Encoder.instance {
case onboarding#Onboarding => onboarding.asJson
case submissionFailed#SubmissionFailed => submissionFailed.asJson
case submitted#Submitted => submitted.asJson
case accountUpdated#AccountUpdated => accountUpdated.asJson
case approvalPending#ApprovalPending => approvalPending.asJson
case active#Active => active.asJson
case rejected#Rejected => rejected.asJson
}
}
case class Account(
id: String,
currency: String,
buyingPower: Double,
cash: Double,
cashWithdrawable: Double,
portfolioValue: Double,
patternDayTrader: Boolean,
tradingBlocked: Boolean,
transfersBlocked: Boolean,
accountBlocked: Boolean,
createdAt: LocalDateTime
)
object Account {
implicit val AccountDecoder: EntityDecoder[IO, Account] = jsonOf[IO, Account]
}
}
I again get some warnings and errors:
[info] Compiling 1 Scala source to /home/tom/code/scalpaca/target/scala-2.12/classes ...
[warn] /home/tom/code/scalpaca/src/main/scala/model/account.scala:27:48: match may not be exhaustive.
[warn] It would fail on the following input: Onboarding
[warn] case onboarding#Onboarding => onboarding.asJson
[warn] ^
[warn] /home/tom/code/scalpaca/src/main/scala/model/account.scala:28:66: match may not be exhaustive.
[warn] It would fail on the following input: SubmissionFailed
[warn] case submissionFailed#SubmissionFailed => submissionFailed.asJson
[warn] ^
[warn] /home/tom/code/scalpaca/src/main/scala/model/account.scala:29:45: match may not be exhaustive.
[warn] It would fail on the following input: Submitted
[warn] case submitted#Submitted => submitted.asJson
[warn] ^
[warn] /home/tom/code/scalpaca/src/main/scala/model/account.scala:30:60: match may not be exhaustive.
[warn] It would fail on the following input: AccountUpdated
[warn] case accountUpdated#AccountUpdated => accountUpdated.asJson
[warn] ^
[warn] /home/tom/code/scalpaca/src/main/scala/model/account.scala:31:63: match may not be exhaustive.
[warn] It would fail on the following input: ApprovalPending
[warn] case approvalPending#ApprovalPending => approvalPending.asJson
[warn] ^
[warn] /home/tom/code/scalpaca/src/main/scala/model/account.scala:32:36: match may not be exhaustive.
[warn] It would fail on the following input: Active
[warn] case active#Active => active.asJson
[warn] ^
[warn] /home/tom/code/scalpaca/src/main/scala/model/account.scala:33:42: match may not be exhaustive.
[warn] It would fail on the following input: Rejected
[warn] case rejected#Rejected => rejected.asJson
[warn] ^
[error] Error while emitting account.scala
[error] assertion failed:
[error] Cannot emit primitive conversion from Lmodel/account/package$AccountStatus; to Lmodel/account/package$Onboarding$; - account.scala
[error] while compiling: /home/tom/code/scalpaca/src/main/scala/model/account.scala
[error] during phase: jvm
[error] library version: version 2.12.8
[error] compiler version: version 2.12.8
[error] reconstructed args: -bootclasspath /home/tom/jdk1.8.0_201/jre/lib/resources.jar:/home/tom/jdk1.8.0_201/jre/lib/rt.jar:/home/tom/jdk1.8.0_201/jre/lib/sunrsasign.jar:/home/tom/jdk1.8.0_201/jre/lib/jsse.jar:/home/tom/jdk1.8.0_201/jre/lib/jce.jar:/home/tom/jdk1.8.0_201/jre/lib/charsets.jar:/home/tom/jdk1.8.0_201/jre/lib/jfr.jar:/home/tom/jdk1.8.0_201/jre/classes:/home/tom/.ivy2/cache/org.scala-lang/scala-library/jars/scala-library-2.12.8.jar -Ypartial-unification -classpath /home/tom/code/scalpaca/target/scala-2.12/classes:/home/tom/.ivy2/cache/io.circe/circe-generic_2.12/jars/circe-generic_2.12-0.11.1.jar:/home/tom/.ivy2/cache/io.circe/circe-parser_2.12/jars/circe-parser_2.12-0.11.1.jar:/home/tom/.ivy2/cache/io.circe/circe-java8_2.12/jars/circe-java8_2.12-0.11.1.jar:/home/tom/.ivy2/cache/org.http4s/http4s-circe_2.12/jars/http4s-circe_2.12-0.20.0-M4.jar:/home/tom/.ivy2/cache/org.http4s/http4s-dsl_2.12/jars/http4s-dsl_2.12-0.20.0-M4.jar:/home/tom/.ivy2/cache/org.http4s/http4s-blaze-client_2.12/jars/http4s-blaze-client_2.12-0.20.0-M4.jar:/home/tom/.ivy2/cache/com.chuusai/shapeless_2.12/bundles/shapeless_2.12-2.3.3.jar:/home/tom/.ivy2/cache/io.circe/circe-jawn_2.12/jars/circe-jawn_2.12-0.11.1.jar:/home/tom/.ivy2/cache/org.http4s/http4s-jawn_2.12/jars/http4s-jawn_2.12-0.20.0-M4.jar:/home/tom/.ivy2/cache/org.http4s/http4s-client_2.12/jars/http4s-client_2.12-0.20.0-M4.jar:/home/tom/.ivy2/cache/org.http4s/http4s-blaze-core_2.12/jars/http4s-blaze-core_2.12-0.20.0-M4.jar:/home/tom/.ivy2/cache/io.circe/circe-core_2.12/jars/circe-core_2.12-0.11.1.jar:/home/tom/.ivy2/cache/org.typelevel/macro-compat_2.12/jars/macro-compat_2.12-1.1.1.jar:/home/tom/.ivy2/cache/org.typelevel/jawn-parser_2.12/jars/jawn-parser_2.12-0.14.1.jar:/home/tom/.ivy2/cache/org.http4s/jawn-fs2_2.12/jars/jawn-fs2_2.12-0.13.0.jar:/home/tom/.ivy2/cache/org.http4s/http4s-core_2.12/jars/http4s-core_2.12-0.20.0-M4.jar:/home/tom/.ivy2/cache/org.http4s/blaze-http_2.12/jars/blaze-http_2.12-0.14.0-M11.jar:/home/tom/.ivy2/cache/io.circe/circe-numbers_2.12/jars/circe-numbers_2.12-0.11.1.jar:/home/tom/.ivy2/cache/org.spire-math/jawn-parser_2.12/jars/jawn-parser_2.12-0.13.0.jar:/home/tom/.ivy2/cache/org.http4s/parboiled_2.12/jars/parboiled_2.12-1.0.0.jar:/home/tom/.ivy2/cache/co.fs2/fs2-io_2.12/jars/fs2-io_2.12-1.0.2.jar:/home/tom/.ivy2/cache/org.eclipse.jetty.alpn/alpn-api/jars/alpn-api-1.1.3.v20160715.jar:/home/tom/.ivy2/cache/com.twitter/hpack/jars/hpack-1.0.2.jar:/home/tom/.ivy2/cache/org.http4s/blaze-core_2.12/jars/blaze-core_2.12-0.14.0-M11.jar:/home/tom/.ivy2/cache/org.log4s/log4s_2.12/jars/log4s_2.12-1.6.1.jar:/home/tom/.ivy2/cache/co.fs2/fs2-core_2.12/jars/fs2-core_2.12-1.0.2.jar:/home/tom/.ivy2/cache/org.typelevel/cats-effect_2.12/jars/cats-effect_2.12-1.1.0.jar:/home/tom/.ivy2/cache/org.slf4j/slf4j-api/jars/slf4j-api-1.7.25.jar:/home/tom/.ivy2/cache/org.scodec/scodec-bits_2.12/jars/scodec-bits_2.12-1.1.7.jar:/home/tom/.ivy2/cache/org.typelevel/cats-core_2.12/jars/cats-core_2.12-1.5.0.jar:/home/tom/.ivy2/cache/org.typelevel/cats-kernel_2.12/jars/cats-kernel_2.12-1.5.0.jar:/home/tom/.ivy2/cache/org.typelevel/cats-macros_2.12/jars/cats-macros_2.12-1.5.0.jar:/home/tom/.ivy2/cache/org.typelevel/machinist_2.12/jars/machinist_2.12-0.6.6.jar:/home/tom/.ivy2/cache/org.scala-lang/scala-reflect/jars/scala-reflect-2.12.6.jar
[error]
[error] last tree to typer: TypeTree(trait Decoder)
[error] tree position: line 53 of /home/tom/code/scalpaca/src/main/scala/model/account.scala
[error] tree tpe: io.circe.Decoder
[error] symbol: abstract trait Decoder in package circe
[error] symbol definition: abstract trait Decoder extends Serializable (a ClassSymbol)
[error] symbol package: io.circe
[error] symbol owners: trait Decoder
[error] call site: constructor package$Account$anon$importedDecoder$macro$28$1$anon$macro$25$1 in package account
[error]
[error] == Source file context for tree position ==
[error]
[error] 50 )
[error] 51
[error] 52 object Account {
[error] 53 implicit val AccountDecoder: EntityDecoder[IO, Account] = jsonOf[IO, Account]
[error] 54 }
[error] 55
[error] 56 }
[error] Error while emitting account.scala
[error] assertion failed: Cannot emit primitive conversion from Lmodel/account/package$AccountStatus; to Lmodel/account/package$SubmissionFailed$; - account.scala
[error] Error while emitting account.scala
[error] assertion failed: Cannot emit primitive conversion from Lmodel/account/package$AccountStatus; to Lmodel/account/package$Submitted$; - account.scala
[error] Error while emitting account.scala
[error] assertion failed: Cannot emit primitive conversion from Lmodel/account/package$AccountStatus; to Lmodel/account/package$AccountUpdated$; - account.scala
[error] Error while emitting account.scala
[error] assertion failed: Cannot emit primitive conversion from Lmodel/account/package$AccountStatus; to Lmodel/account/package$ApprovalPending$; - account.scala
[error] Error while emitting account.scala
[error] assertion failed: Cannot emit primitive conversion from Lmodel/account/package$AccountStatus; to Lmodel/account/package$Active$; - account.scala
[error] Error while emitting account.scala
[error] assertion failed: Cannot emit primitive conversion from Lmodel/account/package$AccountStatus; to Lmodel/account/package$Rejected$; - account.scala
[warn] 7 warnings found
[error] 7 errors found
I can't figure out why Account is affected. If I remove the AccountStatus companion object entirely my project compiles.
I'd like some help getting rid of these errors, your input would still be appreciated. Thanks
To Provide a complete answer to those who might stumble upon this question later:
stsatlantis' suggestion indeed solves one of the problems (thanks for your comment!), while the other one can be solved by slightly modifying the accountStatusEncoder. An alternative solution is to use case classes in your ADT, however, if you already have case objects it is probably because they better fit your needs/domain.
The changes I ended up going with:
object AccountStatus {
implicit val accountStatusEncoder: Encoder[AccountStatus] =
Encoder.instance {
status => status match {
case Onboarding => status.asJson
case SubmissionFailed => status.asJson
case Submitted => status.asJson
case AccountUpdated => status.asJson
case ApprovalPending => status.asJson
case Active => status.asJson
case Rejected => status.asJson
}
}
implicit val accountStatusDecoder: Decoder[AccountStatus] =
List[Decoder[AccountStatus]](
Decoder[Onboarding.type].widen,
Decoder[SubmissionFailed.type].widen,
Decoder[Submitted.type].widen,
Decoder[AccountUpdated.type].widen,
Decoder[ApprovalPending.type].widen,
Decoder[Active.type].widen,
Decoder[Rejected.type].widen
).reduceLeft(_ or _)
implicit val AccountStatusEntityDecoder = jsonOf[IO, AccountStatus]
}

Does not conform the expected type

I have following code snippet:
def determineProducerType(keySerializer: KkSerializer)(valueSerializer: KkSerializer)(props: Properties)
: Eval[KafkaProducer[java.lang.Object, java.lang.Object]] = (keySerializer, valueSerializer) match {
case (KkStringSeDe, KkStringSeDe) => Later(new KafkaProducer[String, String](props))
case (KkStringSeDe, KkByteArraySeDe) => Later(new KafkaProducer[String, Byte](props))
case (KkStringSeDe, KkIntegerSeDe) => Later(new KafkaProducer[String, Integer](props))
case (KkStringSeDe, KkLongSeDe) => Later(new KafkaProducer[String, Long](props))
}
The compiler complains:
[info] Compiling 2 Scala sources to /home/developer/Desktop/scala/PureProducer/target/scala-2.12/classes ...
[error] /home/developer/Desktop/scala/PureProducer/src/main/scala/TheProducer.scala:113:48: type mismatch;
[error] found : org.apache.kafka.clients.producer.KafkaProducer[String,String]
[error] required: org.apache.kafka.clients.producer.KafkaProducer[Object,Object]
[error] Note: String <: Object, but Java-defined class KafkaProducer is invariant in type K.
[error] You may wish to investigate a wildcard type such as `_ <: Object`. (SLS 3.2.10)
[error] Note: String <: Object, but Java-defined class KafkaProducer is invariant in type V.
[error] You may wish to investigate a wildcard type such as `_ <: Object`. (SLS 3.2.10)
[error] case (KkStringSeDe, KkStringSeDe) => Later(new KafkaProducer[String, String](props))
[error] ^
[error] /home/developer/Desktop/scala/PureProducer/src/main/scala/TheProducer.scala:114:51: type mismatch;
[error] found : org.apache.kafka.clients.producer.KafkaProducer[String,Byte]
[error] required: org.apache.kafka.clients.producer.KafkaProducer[Object,Object]
[error] case (KkStringSeDe, KkByteArraySeDe) => Later(new KafkaProducer[String, Byte](props))
[error] ^
[error] /home/developer/Desktop/scala/PureProducer/src/main/scala/TheProducer.scala:115:49: type mismatch;
[error] found : org.apache.kafka.clients.producer.KafkaProducer[String,Integer]
[error] required: org.apache.kafka.clients.producer.KafkaProducer[Object,Object]
[error] Note: String <: Object, but Java-defined class KafkaProducer is invariant in type K.
[error] You may wish to investigate a wildcard type such as `_ <: Object`. (SLS 3.2.10)
[error] Note: Integer <: Object, but Java-defined class KafkaProducer is invariant in type V.
[error] You may wish to investigate a wildcard type such as `_ <: Object`. (SLS 3.2.10)
[error] case (KkStringSeDe, KkIntegerSeDe) => Later(new KafkaProducer[String, Integer](props))
[error] ^
[error] /home/developer/Desktop/scala/PureProducer/src/main/scala/TheProducer.scala:116:46: type mismatch;
[error] found : org.apache.kafka.clients.producer.KafkaProducer[String,Long]
[error] required: org.apache.kafka.clients.producer.KafkaProducer[Object,Object]
[error] case (KkStringSeDe, KkLongSeDe) => Later(new KafkaProducer[String, Long](props))
[error] ^
[error] four errors found
[error] (compile:compileIncremental) Compilation failed
[error] Total time: 2 s, completed Nov 12, 2017 10:39:14 AM
What I am trying to do is, I defined a sum type:
sealed trait KkSerializer
case object KkStringSeDe extends KkSerializer
case object KkByteArraySeDe extends KkSerializer
case object KkIntegerSeDe extends KkSerializer
case object KkLongSeDe extends KkSerializer
When it matches an appropriate sum type, then it should returns corresponding type.
Create an instance of KafkaProducer is:
val producer = new KafkaProducer[String, String](props)
How to solve it?
I think in this case you can just use path dependent types to get what you want:
sealed trait KkSerializer { type Out }
case object KkStringSeDe extends KkSerializer {
type Out = String
}
case object KkByteArraySeDe extends KkSerializer {
type Out = Byte
}
def determineProducerType(k: KkSerializer)(v: KkSerializer)(props: Properties): Eval[KafkaProducer[k.Out, v.Out]] =
Later(new KafkaProducer[k.Out, v.Out](props))

Macro annotations and type parameter

I'm not sure whether its duplicate of Type Parameters on Scala Macro Annotations or not.
I'm trying to get type parameter on macro annotation:
class builder extends StaticAnnotation {
def macroTransform(annottees: Any*) = macro builderMacro.impl
}
//....
val q"new $_[$tpt]().macroTransform(..$_)" = c.macroApplication
val tpe = c.typecheck(tpt).tpe
// also tried
// val tpe = c.typecheck(q"None.asInstanceOf[$tpt]").tpe
Code that uses macro:
object Test2 {
trait TestBuilders
#builder[TestBuilders]
case class TestClass(x: Int, opt1: Option[String], opt2: Option[String]) {
val opts = (opt1, opt2)
}
}
and exception i get:
[error] scala.reflect.macros.TypecheckException: not found: type TestBuilders
[error] at scala.reflect.macros.contexts.Typers$$anonfun$typecheck$2$$anonfun$apply$1.apply(Typers.scala:34)
[error] at scala.reflect.macros.contexts.Typers$$anonfun$typecheck$2$$anonfun$apply$1.apply(Typers.scala:28)
[error] at scala.tools.nsc.typechecker.Contexts$Context.withMode(Contexts.scala:374)
[error] at scala.reflect.macros.contexts.Typers$$anonfun$3.apply(Typers.scala:24)
[error] at scala.reflect.macros.contexts.Typers$$anonfun$3.apply(Typers.scala:24)
[error] at scala.reflect.macros.contexts.Typers$$anonfun$withContext$1$1.apply(Typers.scala:25)
[error] at scala.reflect.macros.contexts.Typers$$anonfun$withContext$1$1.apply(Typers.scala:25)
[error] at scala.tools.nsc.typechecker.Contexts$Context.withMode(Contexts.scala:374)
[error] at scala.reflect.macros.contexts.Typers$$anonfun$1.apply(Typers.scala:23)
[error] at scala.reflect.macros.contexts.Typers$$anonfun$1.apply(Typers.scala:23)
[error] at scala.reflect.macros.contexts.Typers$class.withContext$1(Typers.scala:25)
[error] at scala.reflect.macros.contexts.Typers$$anonfun$typecheck$2.apply(Typers.scala:28)
[error] at scala.reflect.macros.contexts.Typers$$anonfun$typecheck$2.apply(Typers.scala:28)
[error] at scala.reflect.internal.Trees$class.wrappingIntoTerm(Trees.scala:1691)
[error] at scala.reflect.internal.SymbolTable.wrappingIntoTerm(SymbolTable.scala:16)
[error] at scala.reflect.macros.contexts.Typers$class.withWrapping$1(Typers.scala:26)
[error] at scala.reflect.macros.contexts.Typers$class.typecheck(Typers.scala:28)
[error] at scala.reflect.macros.contexts.Context.typecheck(Context.scala:6)
[error] at scala.reflect.macros.contexts.Context.typecheck(Context.scala:6)
[error] at builderMacro$.impl(Macros.scala:55)
what am i doing wrong?
This is a known issue in current macro paradise: https://github.com/scalamacros/paradise/issues/14. Note that if TestBuilders is declared in a different scope, everything should work out.

Map inheritance in slick 2.0

I know there are other questions in stack overflow, but None of them works for me.
I'm trying to map a simple inheritance in slick projection
I try hundreds of combinations, I can't make this compile. I end of with the follow code and the error bellow.
I simplify the case classes because they have much more data. Without inheritance my other layers (controllers, services and interface) will have to deal with complexity, because in this case the model represents real objects that are in trisect inherited, there is no better representation that inheritance for this classes. In the service and controller layer I make the Json representation of the classes be exacted what I need, I can send and consume a Json API that represents my model, the only thing in the way is persisting this representation in relational database, my relational model is capable of persist this entities in an single table inheritance, but translate rows to relational is a pain.
I'm using scala 2.10.3 + sbt 0.13.1
abstract class Pessoa2(val nome:String, val tipo:String)
case class PessoaFisica2(override val nome:String, val cpf:String) extends Pessoa2(nome,"F")
case class PessoaJuridica2(override val nome:String, val cnpj:String) extends Pessoa2(nome, "J")
class PessoaTable(tag: Tag) extends Table[Pessoa2](tag, "PESSOAS"){
// def id = column[Int]("ID", O.PrimaryKey, O.AutoInc)
def nome = column[String]("nome")
def tipo = column[String]("tipo")
def cpf = column[String]("CPF", O.Nullable)
def cnpj = column[String]("CNPJ", O.Nullable)
def * = (nome, tipo, cpf.?, cnpj.?) <> ({
case (nome:String,"F",cpf:Option[String],_) => new PessoaFisica2(nome, cpf.get):Pessoa2
case (nome:String,"J",_,cnpj:Option[String]) => new PessoaJuridica2(nome, cnpj.get):Pessoa2
},{
case PessoaFisica2(nome, Some(cpf)) => Some((nome, "F", cpf, ""))
case PessoaJuridica2(nome, Some(cnpj)) => Some((nome, "J", "", cnpj))
})
}
This ends with the error:
The argument types of an anonymous function must be fully known. (SLS 8.5)
[error] Expected type was: ? => ?
[error] def * = (nome, tipo, cpf.?, cnpj.?) <> ({
[error] ^
[error] /Users/giovanni/Projetos/atende/clientes/app/model/Pessoas.scala:158: type mismatch;
[error] found : Any
[error] required: String
[error] case (nome,"F",cpf,_) => new PessoaFisica2(nome, cpf):Pessoa2
[error] ^
[error] /Users/giovanni/Projetos/atende/clientes/app/model/Pessoas.scala:158: type mismatch;
[error] found : Any
[error] required: String
[error] case (nome,"F",cpf,_) => new PessoaFisica2(nome, cpf):Pessoa2
[error] ^
[error] /Users/giovanni/Projetos/atende/clientes/app/model/Pessoas.scala:159: type mismatch;
[error] found : Any
[error] required: String
[error] case (nome,"J",_,cnpj) => new PessoaJuridica2(nome, cnpj):Pessoa2
[error] ^
[error] /Users/giovanni/Projetos/atende/clientes/app/model/Pessoas.scala:159: type mismatch;
[error] found : Any
[error] required: String
[error] case (nome,"J",_,cnpj) => new PessoaJuridica2(nome, cnpj):Pessoa2
[error] ^
[error] /Users/giovanni/Projetos/atende/clientes/app/model/Pessoas.scala:160: missing parameter type
for expanded function
[error] The argument types of an anonymous function must be fully known. (SLS 8.5)
[error] Expected type was: ? => Option[?]
[error] },{
[error] ^
[error] /Users/giovanni/Projetos/atende/clientes/app/model/Pessoas.scala:157: No matching Shape found.
[error] Slick does not know how to map the given types.
[error] Possible causes: T in Table[T] does not match your * projection. Or you use an unsupported type in a Query (e.g. scala List).
[error] Required level: scala.slick.lifted.ShapeLevel.Flat
[error] Source type: (scala.slick.lifted.Column[String], scala.slick.lifted.Column[String], scala.slick.lifted.Column[Option[String]], scala.slick.lifted.Column[Option[String]])
[error] Unpacked type: (String, String, String, String)
[error] Packed type: Any
[error] def * = (nome, tipo, cpf.?, cnpj.?) <> ({
[error] ^
[error] 7 errors found
Try that:
abstract class Pessoa2(val nome:String, val tipo:String)
case class PessoaFisica2(override val nome:String, val cpf:String) extends Pessoa2(nome,"F")
case class PessoaJuridica2(override val nome:String, val cnpj:String) extends Pessoa2(nome, "J")
class PessoaTable(tag: Tag) extends Table[Pessoa2](tag, "PESSOAS"){
// def id = column[Int]("ID", O.PrimaryKey, O.AutoInc)
def nome = column[String]("nome")
def tipo = column[String]("tipo")
def cpf = column[String]("CPF", O.Nullable)
def cnpj = column[String]("CNPJ", O.Nullable)
def * = (nome, tipo, cpf.?, cnpj.?) <> ({ t : (String, String, Option[String], Option[String])=> t match{
case (nome:String,"F",cpf:Option[String],_) => new PessoaFisica2(nome, cpf.get):Pessoa2
case (nome:String,"J",_,cnpj:Option[String]) => new PessoaJuridica2(nome, cnpj.get):Pessoa2
}},{ k: Pessoa2 => k match{
case PessoaFisica2(nome, cpf) => Some((nome, "F", Some(cpf), Some(""))): Option[(String, String, Option[String], Option[String])]
case PessoaJuridica2(nome, cnpj) => Some((nome, "J", Some(""), Some(cnpj))): Option[(String, String, Option[String], Option[String])]
}})
}
It should compile that way