Type-safe generic case class updates in Scala - scala

I'm attempting to write some code that tracks changes to a record and applies them at a later date. In a dynamic language I'd do this by simply keeping a log of List[(String, Any)] pairs, and then simply applying these as an update to the original record when I finally decide to commit the changes.
I need to be able to introspect over the updates, so a list of update functions isn't appropriate.
In Scala this is fairly trivial using reflection, however I'd like to implement a type-safe version.
My first attempt was to try with shapeless. This works well if we know specific types.
import shapeless._
import record._
import syntax.singleton._
case class Person(name:String, age:Int)
val bob = Person("Bob", 31)
val gen = LabelledGeneric[Person]
val updated = gen.from( gen.to(bob) + ('age ->> 32) )
// Result: Person("Bob", 32)
However I can't figure out how to make this work generically.
trait Record[T]
def update( ??? ):T
}
Given the way shapeless handles this, I'm not sure if this would even be possible?
If I accept a lot of boilerplate, as a poor mans version I could do something along the lines of the following.
object Contact {
sealed trait Field[T]
case object Name extends Field[String]
case object Age extends Field[Int]
}
// A typeclass would be cleaner, but too verbose for this simple example.
case class Contact(...) extends Record[Contact, Contact.Field] {
def update[T]( field:Contact.Field[T], value:T ) = field match {
case Contact.Name => contact.copy( name = value )
case Contact.Age => contact.copy( age = value )
}
}
However this isn't particularly elegant and requires a lot of boilerplate. I could probably write my own macro to handle this, however it seems like a fairly common thing - is there a way to handle this with Shapeless or a similar macro library already?

How about using the whole instance of the class as an update?
case class Contact(name: String, age: Int)
case class ContactUpdate(name: Option[String] = None, age: Option[Int] = None)
object Contact {
update(target: Contact, delta: ContactUpdate) = Contact(
delta.name.getOrElse(target.name)
target.age.getOrElse(delta.age)
)
}
// also, optionally this:
object ContactUpdate {
apply(name: String) = ContactUpdate(name = Option(name))
apply(age: Int) = ContactUpdate(age = Option(age))
}
I think, if you want the really type-safe solution, this is the cleanest and most readable, and also, possibly the least pain to implement, as you don't need to deal with Records, lenses and individual field descriptors, just ContactUpdate(name="foo") creates an update, and updates.map(Contact.update(target, _)) applies them all in sequence.

Related

case class with logic what is the idiomatic way

What is the FP idiomatic way for this: let's say I have this
trait Name
object Name{
def apply(name: String): Name = {
if (name.trim.isEmpty || name.trim.length < 3)
InvalidName
else
ValidName(name.trim)
}
}
case object InvalidName extends Name
case class ValidName(name:String) extends AnyVal with Name
Now I have some helper functions such as
def split = name.splitAt(" ")
//some more functions
which way is more idiomatic:
Put them in the case class it self but that some how makes the case class to contain some logic however I can do something like :
val n = ValidName("john smith")
val (first, last) = n.split
Put them in dedicated object but then the method will look like
def split(n: ValidName) = n.name.splitAt(" ")
Create an object with implicit class that will accept Name and will call the methods
What do you think ?
There is no major issue with adding logic to a case class, especially when it is just extracting the data in a different format. (It becomes problematic when you add data members to a case class).
So I would do option 1 and not worry about it!
In response to the comments, case class is actually just a shortcut for creating a class with a whole bunch of useful pre-implemented methods. In particular, the unapply method allows a case class to be used in pattern matching, and equals does an element-wise comparison of the fields of two instances.
And there are a bunch of other methods to extract the data from the case class in different ways. The most obvious are toString and copy, but there are others like hashCode and all the stuff inherited from Product, such as productIterator.
Since a case class already has methods to extract the data in useful ways, I see no objection to adding your split method as another way of extracting data from the case class.
More idiomatic:
case class Name private (name: String) {
lazy val first :: last :: Nil = name.split(" ").toList
}
object Name {
def fromString (name: String): Either[String, Name] = {
if (name.trim.isEmpty || name.trim.length < 3) Left("Invalid name")
else Right(new Name(name.trim))
}
}
Or maybe this:
case class Name (first: String, last: String) {
lazy val fullName = s"$first $last"
}
object Name {
def fromString (name: String): Either[String, Name] = {
if (name.trim.isEmpty || name.trim.length < 3) Left("Invalid name")
else {
val first :: last :: Nil = name.split(" ").toList
Right(new Name(first, last))
}
}
}
In scala it's more idiomatic to represent failure cases through the use of Either than through inheritance. If you have an instance of N, you can't call any functions on it, you'll probably have to pattern match it. But a type like Either already comes with functions like map, fold, etc. that makes it easier to work with.
Having a private constructor helps ensure that you can only create a valid Name because the only way to create one is through the fromString method.
DO NOT use implicits for this. There's no need and would only make for confusing code. Not really what implicits are for.
I think it depends on context. In this case, if most of the methods you are using are just slight tweaks to String methods, you might want to consider a fourth option:
case class Name(name: String)
implicit def NameToString(n: Name) = n.name
Name("Iron Man").split(" ") // Array(Iron, Man)

Scala create random Objects for test in a functional style

I am trying to figure out which would be the most functional style for this situation
I have a Image model
case class Image(
id: Int,
name: String,
title: String,
permalink: String,
url: String
)
I have a TestHelper object that helps me when I write tests, because it allows me to create random images objects
package utils
import models.Pet
import scala.util.Random
object TestHelper {
val random = new Random()
def randomId = random.nextInt(Integer.MAX_VALUE)
val nameList: List[String] = List("Joycelyn", "Shaunte", "Aurelio", "Jeane", "Carline", "Major", "Shawanna", "Hayden", "Benjamin", "Roxy", "Ardelia", "Yanira", "Tilda", "Claude", "Jonah", "Ilse", "Kieth", "Elmira", "Reid", "Bethann", "Catherine", "Yasuko", "Kia", "Merri", "Ethelyn", "Mallory", "Eustolia", "Matt", "Lynelle", "Christi", "Alane", "Miles", "Ressie", "Darryl", "Kathy", "Hiedi", "Kacy", "Cecila", "Tamar", "Dwayne", "Charlette", "Wanetta", "Sonja", "Celine", "Vina", "Teresa", "Dagny", "Debera", "Doreatha", "Wilda")
def randomImage: Image = {
var id = randomId
var name = nameList(random.nextInt(nameList.length))
var title = name
var permalink = name.toLowerCase
var logoUrl = s"https://www.images.com/${permalink}"
Image(id, name, title, permalink, logoUrl)
}
}
But I know that if I want to write in a functional style I should avoid using var. If I wouldn't use the field name, several times, it would be enough to replace all the vars with defs, but since I need to repeat the value, I am not sure how to write this in a functional style
Take a look at one of our libs(shameless disclaimer).
util-samplers
https://github.com/outworkers/util/blob/develop/util-samplers
It uses macros to navigate the structure of your case classes and generate appropriate samples. It's not a magic bullet but it will deal with most things most of the time, and it will also generate meaningful data wherever possible.
E.g if the field is called name, you will get a "Peter Smith" style result. It's also fully compatible with Scalacheck, but overall pretty basic, with a very simple macro. It's simplicity is guaranteed by having had me write it.
val imageGenerator = Sample.generator[Image]
implicit val imageArb = Sample.arbitrary[Image]
And you can plug that implicit in straight to your functional checkers.
forAll { img: Image => ....
}
If you don't want scalacheck at all, just use the basics:
import com.outworkers.util.samplers._
class MyTest extends FlatSpec {
it should "upload an image to S3" in {
val image = gen[Image]
val images = genList[Image](25)
}
}
If you cannot generate a type or the macro complains, simply write a sampler yourself. In most instances, you'd have something like a trait or object to hold all of them.
object ExtraSamples {
implicit val cantAutomateThis: Sample[java.net.Bla] = new Sample[java.net.Bla] {
override def sample: java.net.Bla = // in here you fill it in manuall....
}
}
Then if you have a case class with a java.net.Bla field, you simply import ExtraSamples._ in places where you do gen, and your manual implementation will be used to construct more complex ones. That's how you can support anything not supported out of the box.
scalacheck-shapeless
This is a different take on the same problem but instead of macros it uses automated typeclass instance derivation capabilities from shapeless. It's not wildly different in its approach from util-samplers, but the code might be slightly more complex, yet higher level.
https://github.com/alexarchambault/scalacheck-shapeless
import org.scalacheck.ScalacheckShapeless._
// If you defined:
// case class Foo(i: Int, s: String, blah: Boolean)
// case class Bar(foo: Foo, other: String)
// sealed trait Base
// case class BaseIntString(i: Int, s: String) extends Base
// case class BaseDoubleBoolean(d: Double, b: Boolean) extends Base
// then you can now do
implicitly[Arbitrary[Foo]]
implicitly[Arbitrary[Bar]]
implicitly[Arbitrary[Base]]
I've never done a side to side comparison, and they are not intended to compete with each other. The first one is extremely fast and lightweight and has minimal overhead as it's just one macro, the shapeless one is more involved and comes with much higher compilation times but it's likely more advanced in terms of what types it can auto-generate.
You can use ScalaCheck for this. ScalaCheck is a port of the functional language Haskell's library QuickCheck, which allows you to write random test example generators in a functional style.
In this particular case, you can simply replace all local vars by vals, because you are not mutating vars anyway.

How best to keep a cached list of member fields, one each for a family of case classes in Scala

This is a follow up to the following question: Fastest way to get the names of the fields of a case class in Scala
I'm trying to find a simple way to provide fast custom serialization (lets say to a list of tuples of (String, Object), which can be converted into a db row in production or an in memory map in unit testing) to a family of case classes in Scala, and it seems that keeping a cached list of a fields of the class may be a promising way of doing this. However, I'm not sure about the cleanest way to do this. I know I can do something like the following:
case class Playlist(
val id: Option[Long],
val title: Option[String],
val album: Option[String],
val artist: Option[String],
val songId: Option[UUID]) {
def serialize = Playlist.fields.map(f => (f.getName, f.get(this)))
}
object Playlist {
val empty = Playlist(None, None, None, None, None)
val fields = Playlist.empty.getClass.getDeclaredFields.toList
fields foreach { _.setAccessible(true) }
}
There a are a couple of things I don't like about this, however:
I don't want to have to use empty from the companion class just to get a cached list of fields
I don't want to have to declare the serialization logic for each case class for which I want this serialization behavior. There are probably a few ways of getting around this, but I'm not sure of the cleanest way that will give correct behavior (worried about mixing reflection and inheritance)
What's the cleanest way to achieve this in Scala?
I think it would be simplest to keep a cache map of Class[_] -> fields separately from any individual case class, such as in a global singleton with a method serialize(instance). This way you don't have to write any extra code in the classes you wish to serialize.
Another way could be to create a trait to mixin to the case classes' companion objects, with the cached list of fields, and an implicit wrapper class to add the serialize method. You can use an implicit ClassTag to initialize fields:
abstract class MyCompanion[T](implicit ctag: ClassTag[T]) {
private val fields = ctag.runtimeClass.getDeclaredFields.toList
fields foreach { _.setAccessible(true) }
implicit class AddSerializeMethod(obj: T) {
def serialize = fields.map(f => (f.getName, f.get(obj)))
}
}
case class C(...) { ... }
object C extends MyCompanion[C]
Unfortunately, it seems you can't make AddSerializeMethod a value class this way.

Custom Scala enum, most elegant version searched

For a project of mine I have implemented a Enum based upon
trait Enum[A] {
trait Value { self: A =>
_values :+= this
}
private var _values = List.empty[A]
def values = _values
}
sealed trait Currency extends Currency.Value
object Currency extends Enum[Currency] {
case object EUR extends Currency
case object GBP extends Currency
}
from Case objects vs Enumerations in Scala. I worked quite nice, till I run into the following problem. Case objects seem to be lazy and if I use Currency.value I might actually get an empty List. It would have been possible to make a call against all Enum Values on startup so that the value list would be populated, but that would be kind of defeating the point.
So I ventured into the dark and unknown places of scala reflection and came up with this solution, based upon the following SO answers. Can I get a compile-time list of all of the case objects which derive from a sealed parent in Scala?
and How can I get the actual object referred to by Scala 2.10 reflection?
import scala.reflect.runtime.universe._
abstract class Enum[A: TypeTag] {
trait Value
private def sealedDescendants: Option[Set[Symbol]] = {
val symbol = typeOf[A].typeSymbol
val internal = symbol.asInstanceOf[scala.reflect.internal.Symbols#Symbol]
if (internal.isSealed)
Some(internal.sealedDescendants.map(_.asInstanceOf[Symbol]) - symbol)
else None
}
def values = (sealedDescendants getOrElse Set.empty).map(
symbol => symbol.owner.typeSignature.member(symbol.name.toTermName)).map(
module => reflect.runtime.currentMirror.reflectModule(module.asModule).instance).map(
obj => obj.asInstanceOf[A]
)
}
The amazing part of this is that it actually works, but it is ugly as hell and I would be interested if it would be possible to make this simpler and more elegant and to get rid of the asInstanceOf calls.
Here is a simple macro based implementation:
import scala.language.experimental.macros
import scala.reflect.macros.blackbox
abstract class Enum[E] {
def values: Seq[E] = macro Enum.caseObjectsSeqImpl[E]
}
object Enum {
def caseObjectsSeqImpl[A: c.WeakTypeTag](c: blackbox.Context) = {
import c.universe._
val typeSymbol = weakTypeOf[A].typeSymbol.asClass
require(typeSymbol.isSealed)
val subclasses = typeSymbol.knownDirectSubclasses
.filter(_.asClass.isCaseClass)
.map(s => Ident(s.companion))
.toList
val seqTSymbol = weakTypeOf[Seq[A]].typeSymbol.companion
c.Expr(Apply(Ident(seqTSymbol), subclasses))
}
}
With this you could then write:
sealed trait Currency
object Currency extends Enum[Currency] {
case object USD extends Currency
case object EUR extends Currency
}
so then
Currency.values == Seq(Currency.USD, Currency.EUR)
Since it's a macro, the Seq(Currency.USD, Currency.EUR) is generated at compile time, rather than runtime. Note, though, that since it's a macro, the definition of the class Enum must be in a separate project from where it is used (i.e. the concrete subclasses of Enum like Currency). This is a relatively simple implementation; you could do more complicated things like traverse multilevel class hierarchies to find more case objects at the cost of greater complexity, but hopefully this will get you started.
A late answer, but anyways...
As wallnuss said, knownDirectSubclasses is unreliable as of writing and has been for quite some time.
I created a small lib called Enumeratum (https://github.com/lloydmeta/enumeratum) that allows you to use case objects as enums in a similar way, but doesn't use knownDirectSubclasses and instead looks at the body that encloses the method call to find subclasses. It has proved to be reliable thus far.
The article "“You don’t need a macro” Except when you do" by Max Afonov
maxaf describes a nice way to use macro for defining enums.
The end-result of that implementation is visible in github.com/maxaf/numerato
Simply create a plain class, annotate it with #enum, and use the familiar val ... = Value declaration to define a few enum values.
The #enum annotation invokes a macro, which will:
Replace your Status class with a sealed Status class suitable for acting as a base type for enum values. Specifically, it'll grow a (val index: Int, val name: String) constructor. These parameters will be supplied by the macro, so you don't have to worry about it.
Generate a Status companion object, which will contain most of the pieces that now make Status an enumeration. This includes a values: List[Status], plus lookup methods.
Give the above Status enum, here's what the generated code looks like:
scala> #enum(debug = true) class Status {
| val Enabled, Disabled = Value
| }
{
sealed abstract class Status(val index: Int, val name: String)(implicit sealant: Status.Sealant);
object Status {
#scala.annotation.implicitNotFound(msg = "Enum types annotated with ".+("#enum can not be extended directly. To add another value to the enum, ").+("please adjust your `def ... = Value` declaration.")) sealed abstract protected class Sealant;
implicit protected object Sealant extends Sealant;
case object Enabled extends Status(0, "Enabled") with scala.Product with scala.Serializable;
case object Disabled extends Status(1, "Disabled") with scala.Product with scala.Serializable;
val values: List[Status] = List(Enabled, Disabled);
val fromIndex: _root_.scala.Function1[Int, Status] = Map(Enabled.index.->(Enabled), Disabled.index.->(Disabled));
val fromName: _root_.scala.Function1[String, Status] = Map(Enabled.name.->(Enabled), Disabled.name.->(Disabled));
def switch[A](pf: PartialFunction[Status, A]): _root_.scala.Function1[Status, A] = macro numerato.SwitchMacros.switch_impl[Status, A]
};
()
}
defined class Status
defined object Status

Best way to use type classes with list parametrized with some base class, abstract class or trait

I think it would be easier to describe a problem with concrete example. Suppose I have have Fruit class hierarchy and Show type class:
trait Fruit
case class Apple extends Fruit
case class Orange extends Fruit
trait Show[T] {
def show(target: T): String
}
object Show {
implicit object AppleShow extends Show[Apple] {
def show(apple: Apple) = "Standard apple"
}
implicit object OrangeShow extends Show[Orange] {
def show(orange: Orange) = "Standard orange"
}
}
def getAsString[T](target: T)(implicit s: Show[T]) = s show target
I also have list of fruits that I would like to show to the user using Show (this is my main goal in this question):
val basket = List[Fruit](Apple(), Orange())
def printList[T](list: List[T])(implicit s: Show[T]) =
list foreach (f => println(s show f))
printList(basket)
This will not compile because List is parametrized with Fruit and I have not defined any Show[Fruit]. What is the best way to achieve my goal using type classes?
I tried to find solution for this problem, but unfortunately have not found any nice one yet. It's not enough to know s in printList function - somehow it needs to know Show[T] for each element of the list. This means, that in order to be able to make this, we need some run-time mechanism in addition to the compile-time one. This gave me an idea of some kind of run-time dictionary, that knows, how to find correspondent Show[T] at run-time.
Implementation of implicit Show[Fruit]can serve as such dictionary:
implicit object FruitShow extends Show[Fruit] {
def show(f: Fruit) = f match {
case a: Apple => getAsString(a)
case o: Orange => getAsString(o)
}
}
And actually very similar approach can be found in haskell. As an example, we can look at Eq implementation for Maybe:
instance (Eq m) => Eq (Maybe m) where
Just x == Just y = x == y
Nothing == Nothing = True
_ == _ = False
The big problem with this solution, is that if I will add new subclass of Fruit like this:
case class Banana extends Fruit
object Banana {
implicit object BananaShow extends Show[Banana] {
def show(banana: Banana) = "New banana"
}
}
and will try to print my basket:
val basket = List[Fruit](Apple(), Orange(), Banana())
printList(basket)
then scala.MatchError would be thrown because my dictionary does not know anything about bananas yet. Of course, I can provide updated dictionary in some context that knows about bananas:
implicit object NewFruitShow extends Show[Fruit] {
def show(f: Fruit) = f match {
case b: Banana => getAsString(b)
case otherFruit => Show.FruitShow.show(otherFruit)
}
}
But this solution is far from perfect. Just imagine that some other library provides another fruit with it's own version of dictionary. It will just conflict with NewFruitShow if I try to use them together.
Maybe I'm missing something obvious?
Update
As #Eric noticed, there is one more solution described here: forall in Scala . It's really looks very interesting. But I see one problem with this solution.
If I use ShowBox, then it will remember concrete type class during it's creation time. So I generally building list with objects and correspondent type classes (so dictionary in present in the list). From the other hand, scala has very nice feature: I can drop new implicits in the current scope and they will override defaults. So I can define alternative string representation for the classes like:
object CompactShow {
implicit object AppleCompactShow extends Show[Apple] {
def show(apple: Apple) = "SA"
}
implicit object OrangeCompactShow extends Show[Orange] {
def show(orange: Orange) = "SO"
}
}
and then just import it in current scope with import CompactShow._. In this case AppleCompactShow and OrangeCompactShow object would be implicitly used instead of defaults defined in the companion object of Show. And as you can guess, list creation and printing happens in different places. If I will use ShowBox, than most probably I will capture default instances of type class. I would like to capture them at the last possible moment - the moment when I call printList, because I even don't know, whether my List[Fruit] will ever be shown or how it would be shown, in the code that creates it.
The most obvious answer is to use a sealed trait Fruit and a Show[Fruit]. That way your pattern matches will complain at compile time when the match is not exhaustive. Of course, adding a new kind of Fruit in an external library will not be possible, but this is inherent in the nature of things. This is the "expression problem".
You could also stick the Show instance on the Fruit trait:
trait Fruit { self =>
def show: Show[self.type]
}
case class Apple() extends Fruit { self =>
def show: Show[self.type] = showA
}
Or, you know, stop subtyping and use type classes instead.