Shapeless define lens for base trait - scala

I have the next code
trait A { val id: Int }
case class B(id: Int) extends A
case class C(id: Int, name: String) extends A
i want to define common lens for all class hierarchy:
import shapeless._
import lens._
val idLens = lens[A] >> 'id
But i get error: could not find implicit value for parameter mkLens: shapeless.MkFieldLens[A,Symbol with shapeless.tag.Tagged[String("id")]]
Is it possible to define lens for all children of trait A?

shapeless doesn't provide an implicit conversion from A to Record. You could define LabelledGeneric[A] to provide the corresponding record type conversion:
import shapeless._
import lens._
import record._
import syntax.singleton._
trait A { val id: Int }
case class B(id: Int) extends A
case class C(id: Int, name: String) extends A
implicit val lgenA = new LabelledGeneric[A] {
type Repr = Record.`'id -> Int`.T
def to(a: A) : Repr = ('id ->> a.id) :: HNil
def from(r: Repr): A = new A { val id = r('id) }
}
val idLens = lens[A] >> 'id
val b = B(7)
println(idLens.get(b)) // 7

Related

Covariant return type implementation

I'm trying to implement a covariant return type for a method in Scala. Let's assume we have the following scenario:
class Animal
class Dog extends Animal
class Cat extends Animal
abstract class M[-T]{
def get[U <: T](): U
}
val container = new M[Animal] {
override def get[U <: Animal](): U = ???
}
How should I do that?
If you're just curious, for example you can use Shapeless
import shapeless.{Generic, HNil}
def get[U <: Animal]()(implicit generic: Generic.Aux[U, HNil]): U =
generic.from(HNil)
get[Dog] // Dog() for case class, Dog#34340fab otherwise
get[Cat] // Cat() for case class, Cat#2aafb23c otherwise
get[Nothing] // doesn't compile
get[Null] // doesn't compile
get[Cat with Dog] // doesn't compile
Or you can use a macro
import scala.language.experimental.macros
import scala.reflect.macros.blackbox
def get[U <: Animal](): U = macro getImpl[U]
def getImpl[U: c.WeakTypeTag](c: blackbox.Context)(): c.Tree = {
import c.universe._
q"new ${weakTypeOf[U]}"
}
Or you can use runtime reflection
import scala.reflect.runtime.universe._
import scala.reflect.runtime
def get[U <: Animal : TypeTag](): U = {
val typ = typeOf[U]
val constructorSymbol = typ.decl(termNames.CONSTRUCTOR).asMethod
val runtimeMirror = runtime.currentMirror
val classSymbol = typ.typeSymbol.asClass
val classMirror = runtimeMirror.reflectClass(classSymbol)
val constructorMirror = classMirror.reflectConstructor(constructorSymbol)
constructorMirror().asInstanceOf[U]
}
(see also example with Java reflection in #KrzysztofAtłasik's answer.)
Or you just can introduce a type class and define its instances manually
trait Get[U <: Animal] {
def get(): U
}
object Get {
implicit val dog: Get[Dog] = () => new Dog
implicit val cat: Get[Cat] = () => new Cat
}
def get[U <: Animal]()(implicit g: Get[U]): U = g.get()
Alternatively, you could use reflection to create new instances. You just need to get implicit classTag:
import scala.reflect.ClassTag
class Animal
class Dog extends Animal
class Cat extends Animal
abstract class M[-T] {
def get[U <: T](implicit ct: ClassTag[U]): U
}
val container = new M[Animal] {
override def get[U <: Animal](implicit ct: ClassTag[U]): U =
//it gets no argument constructor so obviosly it will only work if your classes has no params
ct.runtimeClass.getConstructor().newInstance().asInstanceOf[U]
}
container.get[Dog]

Serialize objects as JSON primitive type in Scala (Play Framework)

check out the following example:
object MyTrait {
def apply(value: Int): MyTrait = value match {
case 0 => A
case 1 => B
case 2 => C
case _ => C
}
def unapply(arg: MyTrait): Int = arg.value
}
case object A extends MyTrait {
val value = 0
}
case object B extends MyTrait {
val value = 1
}
case object C extends MyTrait {
val value = 2
}
case class Test(value: MyTrait)
implicit val testFormatter = Json.format[Test]
all right, this code won't work because i didn't create a JSON serializer for my type "MyTrait". I could do it the way the Play Framework show us to do in the documentation, but it would make a json looking like
{ value: { whatever: 1 } }
and i would like it to look like
{ value: 1 }
In short, i would like my MyTrait objetcs to be interpreted as primitive types (Int) instead of a nested Json Oject.
If someone could help me with that i would be greatful.
Thank you by advance!
The documentation indicates how to provide custom Writes, there to MyTrait to serialize only it's inner value.
sealed trait MyTrait {
def value: Int
}
case object A extends MyTrait {
val value = 0
}
case object B extends MyTrait {
val value = 1
}
case object C extends MyTrait {
val value = 2
}
object MyTrait {
import play.api.libs.json._
def apply(value: Int): MyTrait = value match {
case 0 => A
case 1 => B
case 2 => C
case _ => C
}
def unapply(arg: MyTrait): Int = arg.value
// ---v
implicit val writes: Writes[MyTrait] =
Writes[MyTrait] { v => JsNumber(v.value) }
}
Then when serializing MyTrait instances (note the type ascription bellow is required as Writes is invariant):
Json.toJson(A: MyTrait)
// --> res2: play.api.libs.json.JsValue = 0
And so about Test class:
case class Test(value: MyTrait)
object Test {
import play.api.libs.json._
implicit val writes: OWrites[Test] = Json.writes[Test]
}
Json.toJson(Test(A))
// ---> res1: play.api.libs.json.JsValue = {"value":0}
I would rather recommend to have a look at Enumeratum for the enumerated type MyTrait, or to refactor MyTrait as a Value class and use Json.valueFormat as below.
import play.api.libs.json._
final class MyTrait private(val value: Int) extends AnyVal
object MyTrait {
val A = new MyTrait(0)
val B = new MyTrait(1)
val C = new MyTrait(2)
implicit val format: Format[MyTrait] = Json.valueFormat[MyTrait]
}
case class Test(value: MyTrait)
object Test {
implicit val format: OFormat[Test] = Json.format
}
scala> Json.toJson(Test(MyTrait.A))
res0: play.api.libs.json.JsValue = {"value":0}

Best way to define an implicit class that needs a parameter at runtime

I have an implicit class that needs to use a given parameter at runtime. So I define this implicit in another class that takes this parameter in the constructor. A simplified version of what I am doing is as follows:
case class A(p1: String) {
def foo = println("foo: " + p1)
}
class B(p2: String) {
implicit class Enhancer(a: A) {
implicit def bar = s"bar: ${a.p1}, $p2"
}
}
So when I need to use this class I then do the following:
val a = A("x")
val b = new B("y")
import b._
a.bar
I am wondering if there is a neater way than the above? Specifically the middle two lines where I define the object and then import from it. For example is there any way I could have a one line call to return the implicit class I need?
Try to add implicit parameter to Enhancer.
case class A(p1: String) {
def foo = println("foo: " + p1)
}
class B(val p2: String)
implicit class Enhancer(a: A)(implicit b: B) {
implicit def bar = s"bar: ${a.p1}, ${b.p2}"
}
val a = A("x")
implicit object b extends B("y")
a.bar
or
implicit val b = new B("y")
a.bar
Or
implicit class Enhancer(val a: A) extends AnyVal {
implicit def bar(implicit b: B) = s"bar: ${a.p1}, ${b.p2}"
}

scala circe encoders/decoders for an abstract class with case classes

I want to save a collection of FieldMapping classes as a json string -
abstract class Field {
def clazz: Class[_]
def name: String
}
case class StringField(name: String) extends Field {
override def clazz: Class[_] = classOf[String]
}
case class DateField(name: String) extends Field {
override def clazz: Class[_] = classOf[Date]
}
... etc - full code here:
https://github.com/alexeyOnGitHub/scala-typesafe/blob/master/src/main/scala/com/example/model/Field.scala
Circe code:
import com.example.model.{DateField, Field, FieldMapping, StringField}
import io.circe.generic.semiauto.{deriveDecoder, deriveEncoder}
import io.circe.{Decoder, Encoder}
object CirceBoilerplateForConfigs {
implicit val fieldDecoder: Decoder[StringField] = deriveDecoder[StringField]
implicit val fieldEncoder: Encoder[StringField] = deriveEncoder[StringField]
implicit val dateDecoder: Decoder[DateField] = deriveDecoder[DateField]
implicit val dateEncoder: Encoder[DateField] = deriveEncoder[DateField]
implicit val fooDecoder: Decoder[FieldMapping] = deriveDecoder[FieldMapping]
implicit val fooEncoder: Encoder[FieldMapping] = deriveEncoder[FieldMapping]
}
Error:(14, 65) could not find Lazy implicit value of type
io.circe.generic.decoding.DerivedDecoder[com.example.model.FieldMapping]
implicit val fooDecoder: Decoder[FieldMapping] =
deriveDecoder[FieldMapping] Error:(14, 65)
not enough arguments for method deriveDecoder: (implicit decode:
shapeless.Lazy[io.circe.generic.decoding.DerivedDecoder[com.example.model.FieldMapping]])io.circe.Decoder[com.example.model.FieldMapping].
Unspecified value parameter decode. implicit val fooDecoder:
Decoder[FieldMapping] = deriveDecoder[FieldMapping] Error:(15, 65)
could not find Lazy implicit value of type
io.circe.generic.encoding.DerivedObjectEncoder[com.example.model.FieldMapping]
implicit val fooEncoder: Encoder[FieldMapping] =
deriveEncoder[FieldMapping] Error:(15, 65)
not enough arguments for
method deriveEncoder: (implicit encode:
shapeless.Lazy[io.circe.generic.encoding.DerivedObjectEncoder[com.example.model.FieldMapping]])io.circe.ObjectEncoder[com.example.model.FieldMapping].
Unspecified value parameter encode. implicit val fooEncoder:
Encoder[FieldMapping] = deriveEncoder[FieldMapping]
Field should be a sealed trait (with abstract class or not sealed trait this won't work).
The following code compiles:
import java.util.Date
sealed trait Field {
def clazz: Class[_]
def name: String
}
case class StringField(name: String) extends Field {
override def clazz: Class[_] = classOf[String]
}
case class DateField(name: String) extends Field {
override def clazz: Class[_] = classOf[Date]
}
case class FieldMapping(fieldInConnector1: Option[Field],
fieldInConnector2: Option[Field],
selected: Boolean,
defaultValue: String)
import io.circe.generic.semiauto.{deriveDecoder, deriveEncoder}
import io.circe.{Decoder, Encoder}
object CirceBoilerplateForConfigs {
implicit val stringDecoder: Decoder[StringField] = deriveDecoder[StringField]
implicit val stringEncoder: Encoder[StringField] = deriveEncoder[StringField]
implicit val dateDecoder: Decoder[DateField] = deriveDecoder[DateField]
implicit val dateEncoder: Encoder[DateField] = deriveEncoder[DateField]
implicit val fieldDecoder: Decoder[Field] = deriveDecoder[Field]
implicit val fieldEncoder: Encoder[Field] = deriveEncoder[Field]
implicit val fooDecoder: Decoder[FieldMapping] = deriveDecoder[FieldMapping]
implicit val fooEncoder: Encoder[FieldMapping] = deriveEncoder[FieldMapping]
}

Cannot find Bind instances for Free Monads over Coyoneda when composing functions via Kleisli arrows in scalaz

Thank you in advance for your help
I have 2 functions that I am trying to compose via Kleisli arrows. The functions accept String and produce FreeC. The kleisli arrows are created without an issue but the compiler is complaining that it cannot find. I will cut out some of the code for simplicity:
import scalaz._
import Scalaz._
import Free.FreeC
import Free._
import Kleisli._
trait AppCompose {
def lift[F[_], G[_], A](fa: F[A])(implicit I: Inject[F, G]): FreeC[G, A] =
Free.liftFC(I.inj(fa))
}
object BigBrother {
sealed trait Sensor[A]
case class Log(log: String) extends Sensor[Unit]
case class Filter(log: String) extends Sensor[String]
case class Secure(log: String) extends Sensor[String]
}
import BigBrother.Sensor
class BigBrother[F[_]](implicit I: Inject[Sensor,F]) extends AppCompose {
import BigBrother._
type FreeString[A] = FreeC[F,String]
def log(log: String) = lift(Log(log))
def filter(log: String) = lift(Filter(log))
def secure(log: String) = lift(Secure(log))
def filterAndSecure(phrase: String) = for {
f <- filter(phrase)
s <- secure(f)
} yield s
// kleisli composition attempt - alternative to filterAndSecure
val fk = kleisli[FreeString, String, String](filter _)
val sk = kleisli[FreeString, String, String](secure _)
val fAndS = fk >=> sk // this is where we have a compilation issue
}
For some reason what i get is this compilation error:
could not find implicit value for parameter b: scalaz.Bind[FreeString]
[error] val fAndS = sk >=> fk
feels like the implicit should be resolved since FreeC in a monad instance that implements a Bind trait and i am importing all of the Free implicit instances via import Free._
what am I missing here?
Thank you in advance!
Thank you Travis for your help. Bad type declaration was actually one of the culprits. With some help from the scalaz community via google groups and some tinkering here is the answer:
class BigBrother[F[_]](implicit I: Inject[Sensor,F]) extends AppCompose {
import BigBrother._
def log(log: String) = lift(Log(log))
def filter(log: String) = lift(Filter(log))
def secure(log: String) = lift(Secure(log))
def filterAndSecure(phrase: String) = for {
f <- filter(phrase)
s <- secure(f)
} yield s
type CoyoF[A] = Coyoneda[F, A]
type FreeCoF[A] = Free[CoyoF,A]
implicit val MonadFreeSensor = Free.freeMonad[FreeCoF]
// kleisli composition attempt - alternative to filterAndSecure
val fk = kleisli[FreeCoF, String, String](filter _)
val sk = kleisli[FreeCoF, String, String](secure _)
val fAndS = fk >=> sk
}
key is the correct type declaration and providing the type class monad instance for FreeCoF implicit val MonadFreeSensor = Free.freeMonad[FreeCoF]