Actually I've stuck with functional programming code style and project structure. When programming in Java I knew where to place all my logic, but I'm not familiar with the functional style.
Actually I try to make my Scala classes in my current project immutable. Then I want to use scalaz.Lens and scalaz.PLens to change my objects in future(actually create new).
In all Lense examples people place a code in one object, which extends App trait to simply show how it works. But in real-life example should be some appropriate place to write those Lenses.
In Java all mutators and accessors placed in classes itself. But with Lenses I don't know where to write them.
Will appreciate any advice
Typically lenses are hold in companion objects, like
package package1
import monocle.Iso
import monocle.macros.Lenses
#Lenses
case class Name(first: String, last: String, mid: Option[String]) {
def fullName = s"$first ${mid.fold("")(_ + " ")}$last"
}
object Name {
val fullName = Iso[Name, String](_.fullName)(_.split(' ') match {
case Array() => Name("", "", None)
case Array(name) => Name(name, "", None)
case Array(first, last) => Name(first, last, None)
case Array(first, mid, last, _*) => Name(first, last, Some(mid))
})
}
and
package package2
import monocle.macros.Lenses
import package1._
#Lenses
case class User(name: Name, age: Int)
object User {
val fullName = name ^<-> Name.fullName
}
Here the #Lenses macro annotation will automatically put lenses for simple fields in companion objects
Related
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.
Say I have 2 case classes:
case class Basic(id: String, name) extends SomeBasicTrait
case class Info (age: Int, country: String, many other fields..) extends SomeInfoTrait
and want to create a case class that has all fields from both of those case classes. This is a possible way:
case class Full(bs: Basic, meta: Info) extends SomeBasicTrait with SomeInfoTrait {
val id = bs.id
val name = bs.name
val age = meta.age
val country = meta.country
// etc
}
But it's a lot of boilerplate code. Is there any way to avoid this?
I couldn't find a way to achieve this in Shapeless but maybe there is..
[Update]
#jamborta 's comment helps and is basically this:
case class FullTwo(id: String, name: String, age:Int, country:String)
val b = Basic("myid", "byname")
val i = Info(12, "PT")
Generic[FullTwo].from(Generic[Basic].to(b) ++ Generic[Info].to(i))
The problem with this solution is that it still requires defining every field in the arguments of the FullTwo class, so that every time a change to Basic or Info is made, we also have to remember to change FullTwo as well.
Is there any way to create dynamically at compile time a case class equal to FullTwo?
I have multiple case classes representing values in DB for ex User which saves user based properties like name / age / address and CallLog which saves timestamp / status_of_call
What i want to achieve
I want to have a helper function which accepts list of models and checks if the list is empty then returns "error" otherwise should return json array of the list.
My Approach
I want to have a trait which groups certain models in it and the helper method will accept either the trait or List of it in order to check or may be have a generic which implements the trait.
Problem
Since implicit writes are tightly coupled with the model class, compiler throws the error on the line Json.toJson(list)
Things i have tried
Kept implicit in trait and got recursive type error
I am scala noob pardon me if this sounds silly
Thanks in advance
Since User, CallLog, etc. will be serialized differently, Each Writes[T] will be different for each implementation of your Model trait, so a Writes[Model] has to know about the implementation it is trying to serialize.
It is therefore not possible to have it part of the Model trait, because this information isn't known yet when you define it.
A workaround in your case would be to define your Writes[Model] in the scope of your helper function instead.
An implementation of your helper function could be like this :
import play.api.libs.json.{JsValue, Json, Writes}
sealed trait Model
case class User(name: String, age: String, address: String) extends Model
object User {
implicit val userWrites = Json.writes[User]
}
case class CallLog(timestamp: String, status_of_call: String) extends Model
object CallLog {
implicit val callLogWrites = Json.writes[CallLog]
}
implicit val modelWrites = new Writes[Model] {
override def writes(o: Model): JsValue = o match {
case u: User => Json.toJson(u)
case cl: CallLog => Json.toJson(cl)
}
}
def helper(models: Model*): Either[JsValue, String] = models match {
case Nil => Right("Error")
case _ => Left(Json.toJson(models))
}
helper(User("John", "32", "..."))
helper(User("John", "32", "..."), CallLog("now", "In progress"))
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.
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.