Read case class object from string in Scala (something like Haskell's "read" typeclass)

haskell, scala, serialization

Solution

dflemstr answered more towards setting up the actual `read` method- I'll answer more for the actual parsing method.

My approach has two objects that can be used in scala's pattern matching blocks. `AsInt` lets you match against strings that represent `Int`s, and `PersonString` is the actual implementation for `Person` deserialization.

object AsInt {
  def unapply(s: String) = try{ Some(s.toInt) } catch {
    case e: NumberFormatException => None
  }
}

val PersonRegex = "Person\\((.*),(\\d+)\\)".r

object PersonString {
  def unapply(str: String): Option[Person] = str match {
    case PersonRegex(name, AsInt(age)) => Some(Person(name, age))
    case _ => None
  }
}

The magic is in the `unapply` method, which scala has syntax sugar for. So using the `PersonString` object, you could do

val person = PersonString.unapply("Person(Bob,42)")
//  person will be Some(Person("Bob", 42))

or you could use a pattern matching block to do stuff with the person:

"Person(Bob,42)" match {
  case PersonString(person) => println(person.name + " " + person.age)
  case _ => println("Didn't get a person")
}

Problem

I'd like to read a string as an instance of a case class. For example, if the function were named "read" it would let me do the following: ``` case class Person(name: String, age: Int) val personString: String = "Person(Bob,42)" val person: Person = read(personString) ``` This is the same behavior as the read typeclass in Haskell.

Original source