I am still learning scala and attempting to use circe's decoders, but running into a little trouble with a context bound I think. I'm unsure why scala is expecting this implicit argument?
abstract class Input[A](namedDecoder: String) extends Decoder[A]
abstract class Test[T: Input](args: Int)
case class InputImpl(hash: String, namedDecoder: String) extends Input(namedDecoder)
class TestImpl(x: Int) extends Test[InputImpl](x)
I'm getting an error: No implicit arguments of type Input[InputImpl] and I'm a little confused what I'm missing here. Thanks for any help!
Actually, I think you don't want Input to be a Decoder but rather have an instance of Decoder associated with it.
Check this code:
abstract class Input[A](namedDecoder: String)
final case class InputImpl(hash: String, namedDecoder: String) extends Input(namedDecoder)
abstract class Test[T <: Input : Decoder](args: Int)
class TestImpl(x: Int) extends Test[InputImpl](x)
Otherwise, I really don't understand what is that you need to do, but maybe something like this?
trait Input[A] {
def decoder: Decoder[A]
def namedDecoder: String
}
object Input {
final class InputImpl[A](
val hash: String,
override final val namedDecoder: String,
override final val decoder: Decoder[A]
) extends Input[A]
implicit final def fromDecoder[A](implicit ev: Decoder[A]): Input[A] =
new InputImpl(hash = "someHash", namedDecoder = "someName", decoder = ev)
}
abstract class Test[T: Input](args: Int)
final class TestImpl(x: Int) extends Test[String](x)
Although Input doesn't feel like a typeclass, why do you want to pass it implicitly? From where would things like hash and namedDecoder even come from? Those feel like just normal parameters.
Related
Consider the following segment of code -
abstract class Vehicle {
val name: String
}
case class Car(name: String) extends Vehicle
case class Truck(name: String) extends Vehicle
abstract class VehicleContainer[T <: Vehicle] {
def compare(that: VehicleContainer[T]): Int
}
class CarContainer(wheels: Int) extends VehicleContainer[Car] {
override def compare(that: CarContainer): Int = ???
}
The intention here is to have a compare method on the VehicleContainer that can be defined for each specific instance of VehicleContainer. The compare method comparison clause needs to be unique for each instance, because it could be comparing using attributes specific to that instance and hence not defined in the abstract base class VehicleContainer.
The trouble is that this does not work in it's current form, i.e. the override for compare is illegal. What I am not able to understand is how to accomplish this - define a base class that indicates that the sub classes need to implement a compare method, where the method argument to that compare method is that sub class itself. Would appreciate a pointer to the right concept here if it's some straightforward generics concept that I am missing here.
Thanks!
One way to solve your problem could be use of F-bounded polymophism. You would just need one additional type parameter:
abstract class Vehicle {
val name: String
}
case class Car(name: String) extends Vehicle
case class Truck(name: String) extends Vehicle
abstract class VehicleContainer[T <: Vehicle, V <: VehicleContainer[T, V]] {
def compare(that: V): Int
}
class CarContainer(wheels: Int) extends VehicleContainer[Car, CarContainer] {
override def compare(that: CarContainer): Int = ???
}
I am performing a repetitive task of creating a object that has same internal contents and hence thought of creating a generic method that would help me achieve this.
The internal object is as follows
case class Data(value: Int)
I have a base trait as follows
trait Base
There are a couple of classes that extend this trait
case class A(data: Data) extends Base
case class B(data: Data) extends Base
case class C(data: Data) extends Base
The generic method that I am trying to write to create the object
def getObject[T <: Base](data: Data, t: T) = {
T(data)
}
However, while trying to do so, I get a compile-time error saying that
Cannot resolve symbol T
Can you please let me know what I am missing in this method implementation.
Note:- This is a very simplistic implementation of what I am trying to do in my code.
Due to type-erasure, you can't use generic type to create a new instance of an object.
You could use ClassTag to capture a class of T at runtime:
case class Data(value: Int)
trait Base
case class A(data: Data) extends Base
case class B(data: Data) extends Base
case class C(data: Data) extends Base
def getObject[T <: Base](data: Data)(implicit ct: ClassTag[T]): T =
ct.runtimeClass.getDeclaredConstructors.head.newInstance(data).asInstanceOf[T]
val a: A = getObject[A](Data(1))
val b: B = getObject[B](Data(2))
val c: C = getObject[C](Data(3))
As cchantep noticed, it has a drawback, that if your case class doesn't have a constructor with single argument Data, this function will fail at runtime.
Consider typeclass solution for compile-time safety
final case class Data(value: Int)
final case class A(data: Data)
final case class B(data: Data)
final case class C(data: Data)
trait BaseFactory[T] {
def apply(data: Data): T
}
object BaseFactory {
def apply[T](data: Data)(implicit ev: BaseFactory[T]): T = ev.apply(data)
implicit val aBaseFactory: BaseFactory[A] = (data: Data) => A(data)
implicit val bBaseFactory: BaseFactory[B] = (data: Data) => B(data)
implicit val cBaseFactory: BaseFactory[C] = (data: Data) => C(data)
}
val data = Data(42)
BaseFactory[A](data) // res0: A = A(Data(42))
BaseFactory[B](data) // res1: B = B(Data(42))
BaseFactory[C](data) // res2: C = C(Data(42))
I want to define circular referenced structure JSON with spray-json, so I try to define like below.
final case class A(b: B)
final case class B(a: A)
trait AProtocol extends DefaultJsonProtocol {
implicit val aProtocol: RootJsonFormat[A] = rootFormat(lazyFormat(jsonFormat1(A)))
}
But I got an error which is
<console>:18: error: could not find implicit value for evidence parameter of type MyProtocol.this.JF[B]
implicit val aProtocol: RootJsonFormat[A] = rootFormat(lazyFormat(jsonFormat1(A)))
Please give me some advices.
Well, you have jsonFormat for A but what with B. You are using lazyFormat well but completely forgot about other dependency. Try this:
final case class A(b: B)
final case class B(a: A)
trait AProtocol extends DefaultJsonProtocol {
implicit val aProtocol: RootJsonFormat[A] = rootFormat(lazyFormat(jsonFormat1(A)))
implicit val bProtocol: RootJsonFormat[B] = rootFormat(lazyFormat(jsonFormat1(B)))
}
I am still pretty new to Scala and looking at using Slick.
I also am looking at Accord (github.com/wix/accord) for validation.
Accord's validation seems to be on objects as a whole, but I want to be able to define validators for field types, so I've thought of using type aliasing using value classes so that I can easily re-use validations across various case classes that use those field types.
So, I've defined the following:
object FieldTypes {
implicit class ID(val i: Int) extends AnyVal
implicit class UserPassword(val s: String) extends AnyVal
implicit class Email(val s: String) extends AnyVal
implicit class Name(val s: String) extends AnyVal
implicit class OrgName(val s: String) extends AnyVal
implicit class OrgAlias(val s: String) extends AnyVal
}
package object validators {
implicit val passwordValidator = validator[UserPassword] { _.length is between(8,255) }
implicit val emailValidator = validator[Email] { _ is notEmpty }
implicit val nameValidator = validator[Name] { _ is notEmpty }
implicit val orgNameValidator = validator[OrgName] { _ is notEmpty }
implicit val teamNameValidator = validator[TeamName] { _ is notEmpty }
}
case object Records {
import FieldTypes._
case class OrganizationRecord(id: ID, uuid: UUID, name: OrgName, alias: OrgAlias)
case class UserRecord(id: ID, uuid: UUID, email: Email, password: UserPassword, name: Name)
case class UserToOrganizationRecord(userId: ID, organizationId: ID)
}
class Tables(implicit val p: JdbcProfile) {
import FieldTypes._
import p.api._
implicit object JodaMapping extends GenericJodaSupport(p)
case class LiftedOrganizationRecord(id: Rep[ID], uuid: Rep[UUID], name: Rep[OrgName], alias: Rep[OrgAlias])
implicit object OrganizationRecordShape extends CaseClassShape(LiftedOrganizationRecord.tupled, OrganizationRecord.tupled)
class Organizations(tag: Tag) extends Table[OrganizationRecord](tag, "organizations") {
def id = column[ID]("id", O.PrimaryKey)
def uuid = column[UUID]("uuid", O.Length(36, varying=false))
def name = column[OrgName]("name", O.Length(32, varying=true))
def alias = column[OrgAlias]("alias", O.Length(32, varying=true))
def * = LiftedOrganizationRecord(id, uuid, name, alias)
}
val organizations = TableQuery[Organizations]
}
Unfortunately, I clearly misunderstand or overestimate the power of Scala's implicit conversions. My passwordValidator doesn't seem to recognize that there is a length property to UserPassword and my * declaration on my Organizations table doesn't seem to think that it complies to the shape defined in LiftedOrganizationRecord.
Am I just doing something really dumb here on the whole? Should I not be even trying to use these kinds of custom types and simply use standard types instead, defining my validators in a better way? Or is this an okay way of doing things, but I've just forgotten something simple?
Any advice would be really appreciated!
Thanks to some helpful people on the scala gitter channel, I realized that the core mistake was a misunderstanding of the conversion direction for value classes. I had understood it to be ValueClass -> WrappedValueType, but it's actually WrappedValueType -> ValueClass. Thus, Slick wasn't seeing, as an exmaple, ID as an Int.
I'd like to "lock" a class, which is extended from a trait. Is it possible in Scala?
For example I have:
trait A {
val boris: String
val john: String
val number: Int
}
class B extends A {
// do something with these values
}
but can I ensure, that in class B no new values will be added if those aren't declared in trait A?
Thanks for your answers.
You cannot.
But if you simply mark the trait as sealed and provide a default implementation:
sealed trait A { val boris: String }
final class B(val boris: String) extends A {}
then people are free to create implicit value classes that make it look like new functionality has been added (except without actually creating the class):
implicit class MyB(val underlying: B) extends AnyVal {
def sirob = underlying.boris.reverse
}
(new B("fish")).sirob // "hsif"
You can also let the classes take a type parameter as a marker if you want to keep them straight at compile-time (though not runtime):
sealed trait A[T] { val boris: String }
final class B[T](val boris: String) extends A[T] {}
implicit class MyB(val underlying: B[Int]) extends AnyVal {
def sirob = underlying.boris.reverse
}
(new B[Int]("fish")).sirob // "hsif"
(new B[Char]("fish")).sirob // error: value sirob is not a member of B[Char]
So you could--especially with 2.10--simply lock everything and let users enrich the original interface this way.
I'm not sure if this covers your intended use case, though; it doesn't provide any inheritance.
Based on your example and my guess at what you are actually trying to do, you may want to consider just using case classes.
Extending a case class is generally avoided (I think it will spit out deprecation warnings if you try), so that will prevent people from wanting to extend your class in order to add functionality.
Translating your example into a case class:
case class A (boris: String, john: String, number: Int)
Then instead of extending A to change its values, you'd just make a new instance, e.g.
val a2 = someOtherA.copy(john="Doe")