Applying validation from HList to a case class - scala

In attempting to do validation with application functors (Monad to catch multiple exceptions (not just fail on single)), I came across a hard limit in scalaz that disallows more than 14 functors, so a helpful comment from here (https://github.com/scalaz/scalaz/issues/504#issuecomment-23626237) navigated me to use HLists instead of applicative functors
Now it works perfectly fine (after having to manually put in this sequence file from here since its not in maven https://github.com/typelevel/shapeless-contrib/blob/master/scalaz/main/scala/sequence.scala?source=c)
My question is, and I know this is possible, how would you go about automatically instantiating the case class Foo(i:Int,s:String) without having to manually match the pattern with a case, only to just reapply the parameters again
Essentially I want to do something like this
case class Foo(i:Int,s:String)
implicit def TwoFoo = Iso.hlist(Foo.apply _, Foo.unapply _)
val someFoo = sequence(
1.successNel[Int] ::
"2".successNel[String] ::
HNil
).map { Foo.apply _} // Note this doesn't work
someFoo match {
case Success(a) => println(a)
case Failure(a) => {
println("failure")
println(a)
}
}

First for a minor point: the type parameter for successNel is the error type, not the success type, so it needs to be the same across all the arguments to sequence.
So we can write the following (assuming our errors are strings):
import shapeless._, contrib.scalaz._
import scalaz._, syntax.validation._
case class Foo(i: Int, s: String)
implicit val fooIso = Iso.hlist(Foo.apply _, Foo.unapply _)
val valHList = sequence(1.successNel[String] :: "2".successNel[String] :: HNil)
This gives us an Int :: String :: HNil inside a validation. Now we can use our isomorphism:
scala> valHList.map(fooIso.from)
res0: scalaz.Validation[scalaz.NonEmptyList[String],Foo] = Success(Foo(1,2))
No need to deconstruct the list and apply the Foo constructor manually.

Related

Functional Programming exercise with Scala

I have recently started reading the book Functional Programming in Scala by Paul Chiusano and Rúnar Bjarnason, as a means to learn FP. I want to learn it because it will open my head a bit, twist my way of thinking and also hopefully make me a better programmer overall, or so I hope.
In their book, Chp. 3, they define a basic singly-linked-list type as follows:
package fpinscala.datastructures
sealed trait List[+A]
case object Nil extends List[Nothing]
case class Cons[+A](head: A, tail: List[A]) extends List[A]
object List {
def sum(ints: List[Int]): Int = ints match {
case Nil => 0
case Cons(x,xs) => x + sum(xs)
}
def product(ds: List[Double]): Double = ds match {
case Nil => 1.0
case Cons(0.0, _) => 0.0
case Cons(x,xs) => x * product(xs)
}
def apply[A](as: A*): List[A] =
if (as.isEmpty) Nil
else Cons(as.head, apply(as.tail: _*))
}
I'm now working on implementing the tail method, which shall work similarly to the tail method defined in Scala libraries. I guess that the idea here, is to define a tail method inside the List object, what they call a companion method, and then call it normally in another file (like a Main file).
So far, I have this:
def tail[A](ls: List[A]): List[A] = ls match {
case Nil => Nil
case Cons(x,xs) => xs
}
Then I created a Main file in another folder:
package fpinscala.datastructures
object Main {
def main(args:Array[String]):Unit = {
println("Hello, Scala !! ")
val example = Cons(1, Cons(2, Cons(3, Nil)))
val example2 = List(1,2,3)
val example3 = Nil
val total = List.tail(example)
val total2 = List.tail(example3)
println(total2)
}
}
This works and gives me:
Hello, Scala !!
Cons(2,Cons(3,Nil))
My question is:
Is this the correct way to write the tail method, possibly, as the authors intended? And is this package structure correct? Because it feels very wrong to me, although I just followed the authors package.
I also don't know if I should have used a specific type instead of writing a polymorphic method (is this the name?)...
Bear with me, for I am a newbie in the art of FP.
In the default Scala list implementation, attempting to take the tail of an empty list would throw an UnsupportedOperationException. So you might want something more like
def tail[A](ls: List[A]): List[A] = ls match {
case Nil => throw new UnsupportedOperationException()
case Cons(x,xs) => xs
}
Also, qantik's answer where he suggests using the :: operator would work with Scala's default list implementation, but since there isn't a :: method defined on this custom list implementation it won't work.
Finally, you may want to consider defining tail so that instead of doing
val list = List(1, 2, 3)
val restOfList = tail(list).
you could instead do
val list = List(1, 2, 3)
val restOfList = list.tail
That would require defining the method on the List trait, as opposed to in the List object.
Looks okay. What about?
def tail[A](xs: List[A]): List[A] = xs match {
case Nil => Nil
case head :: xxs => xxs
}

Scala Tree Match Case

I'm fairly new to Scala and very new to writing macros and looking for a little help/advise. I have the following code...
trait ValidationRule
case class Required() extends ValidationRule
case class HasLength(l: Int) extends ValidationRule
case class Person(name: String)
myMacro[Person] { p => p.name.is(Required(), HasLength(255)) }
Obviously there is some missing code here but this is just pseudo to get the question out.
So given a Tree representing p => p.name.is(Required(), HasLength(255)) I'm trying to write a match/case to select out all expressions representing a ValidationRule. Something like:
case TypeApply(Select(_, ....
Can anyone suggest the best match case to be able to extract a List of Trees that represent each "all" ValidationRules from within the "is" method?
You should definitely look into Quasiquotes.
Quasiquotes are used to do two things: to build Trees, and to pattern match Trees. They allow you to express the tree that you want to work with in terms of the equivalent Scala code. You let the quasiquote library deal with how Scala code maps to a Tree graph, and that's a good thing!
You can play around with them in the REPL, though the results might be slightly different in the macro universe:
scala> import scala.reflect.runtime.universe._
scala> showRaw(cq"p => p.name.is(Required(), HasLength(255))")
res0: String = CaseDef(
Bind(
TermName("p"),
Ident(termNames.WILDCARD)),
EmptyTree,
Apply(
Select(
Select(
Ident(TermName("p")),
TermName("name")),
TermName("is")),
List(
Apply(
Ident(TermName("Required")),
List()),
Apply(
Ident(TermName("HasLength")),
List(Literal(Constant(255)))))))
The other thing you can do with Quasiquotes is to actually use them to pattern match.
scala> val fromTree = cq"p => p.name.is(Required(), HasLength(255))"
scala> val cq"p => p.name.is($x, $y)" = fromTree
x: reflect.runtime.universe.Tree = Required()
y: reflect.runtime.universe.Tree = HasLength(255)
Now, you have to be careful, because that pattern ONLY matches if the user named their pattern variable p.
scala> val fromTree = cq"x => x.name.is(Required(), HasLength(255))"
scala> val cq"p => p.name.is($x, $y)" = fromTree
scala.MatchError: case (x # _) => x.name.is(Required(), HasLength(255)) (of class scala.reflect.internal.Trees$CaseDef)
... 33 elided
Instead, you'll want to be a bit more generic:
scala> val cq"${p1:TermName} => ${p2:TermName}.name.is($x, $y)" = fromTree
p1: reflect.runtime.universe.TermName = x
p2: reflect.runtime.universe.TermName = x
x: reflect.runtime.universe.Tree = Required()
y: reflect.runtime.universe.Tree = HasLength(255)
scala> p1 == p2
res2: Boolean = true
And, of course, if you were doing this as part of a pattern match, you could do:
case cq"${p1:TermName} => ${p2:TermName}.name.is($x, $y)" if p1 == p2 =>
???
Keep in mind that Macros are a deep, dark hole. If you're just getting started, expect to spend a lot of time getting your macro code correct. After that, expect to spend a lot of time dealing with edge cases.

Scala, pattern matching on a tuple of generic trait, checking if types are equal

I know a lot of questions exist about type erasure and pattern matching on generic types, but I could not understand what should I do in my case from answers to those, and I could not explain it better in title.
Following code pieces are simplified to present my case.
So I have a trait
trait Feature[T] {
value T
def sub(other: Feature[T]): Double
}
// implicits for int,float,double etc to Feature with sub mapped to - function
...
Then I have a class
class Data(val features: IndexedSeq[Feature[_]]) {
def sub(other: Data): IndexedSeq[Double] = {
features.zip(other.features).map {
case(e1: Feature[t], e2: Feature[y]) => e1 sub e2.asInstanceOf[Feature[t]]
}
}
}
And I have a test case like this
case class TestFeature(val value: String) extends Feature[String] {
def sub(other: Feature[String]): Double = value.length - other.length
}
val testData1 = new Data(IndexedSeq(8, 8.3f, 8.232d, TestFeature("abcd"))
val testData2 = new Data(IndexedSeq(10, 10.1f, 10.123d, TestFeature("efg"))
testData1.sub(testData2).zipWithIndex.foreach {
case (res, 0) => res should be (8 - 10)
case (res, 1) => res should be (8.3f - 10.1f)
case (res, 2) => res should be (8.232d - 10.123d)
case (res, 3) => res should be (1)
}
This somehow works. If I try sub operation with instances of Data that have different types in same index of features, I get a ClassCastException. This actually satisfies my requirements, but if possible I would like to use Option instead of throwing an exception. How can I make following code work?
class Data(val features: IndexedSeq[Feature[_]]) {
def sub(other: Data): IndexedSeq[Double] = {
features.zip(other.features).map {
// of course this does not work, just to give idea
case(e1: Feature[t], e2: Feature[y]) if t == y => e1 sub e2.asInstanceOf[Feature[t]]
}
}
}
Also I am really inexperienced in Scala, so I would like to get feedback on this type of structure. Are there another ways to do this and which way would make most sense?
Generics don't exist at runtime, and an IndexedSeq[Feature[_]] has forgotten what the type parameter is even at compile time (#Jatin's answer won't allow you to construct a Data with a list of mixed types of Feature[_]). The easiest answer might be just to catch the exception (using catching and opt from scala.util.control.Exception). But, to answer the question as written:
You could check the classes at runtime:
case (e1: Feature[t], e2: Feature[y]) if e1.value.getClass ==
e2.value.getClass => ...
Or include the type information in the Feature:
trait Feature[T] {
val value: T
val valueType: ClassTag[T] // write classOf[T] in subclasses
def maybeSub(other: Feature[_]) = other.value match {
case valueType(v) => Some(actual subtraction)
case _ => None
}
}
The more complex "proper" solution is probably to use Shapeless HList to preserve the type information in your lists:
// note the type includes the type of all the elements
val l1: Feature[Int] :: Feature[String] :: HNil = f1 :: f2 :: HNil
val l2 = ...
// a 2-argument function that's defined for particular types
// this can be applied to `Feature[T], Feature[T]` for any `T`
object subtract extends Poly2 {
implicit def caseFeatureT[T] =
at[Feature[T], Feature[T]]{_ sub _}
}
// apply our function to the given HLists, getting a HList
// you would probably inline this
// could follow up with .toList[Double]
// since the resulting HList is going to be only Doubles
def subAll[L1 <: HList, L2 <: HList](l1: L1, l2: L2)(
implicit zw: ZipWith[L1, L2, subtract.type]) =
l1.zipWith(l2)(subtract)
That way subAll can only be called for l1 and l2 all of whose elements match, and this is enforced at compile time. (If you really want to do Options you can have two ats in the subtract, one for same-typed Feature[T]s and one for different-typed Feature[_]s, but ruling it out entirely seems like a better solution)
You could do something like this:
class Data[T: TypeTag](val features: IndexedSeq[Feature[T]]) {
val t = implicitly[TypeTag[T]]
def sub[E: TypeTag](other: Data[E]): IndexedSeq[Double] = {
val e = implicitly[TypeTag[E]]
features.zip(other.features).flatMap{
case(e1, e2: Feature[y]) if e.tpe == t.tpe => Some(e1 sub e2.asInstanceOf[Feature[T]])
case _ => None
}
}
}
And then:
case class IntFeature(val value: Int) extends Feature[Int] {
def sub(other: Feature[Int]): Double = value - other.value
}
val testData3 = new Data(IndexedSeq(TestFeature("abcd")))
val testData4 = new Data(IndexedSeq(IntFeature(1)))
println(testData3.sub(testData4).zipWithIndex)
gives Vector()

How to make Scala's type system catch this MatchError?

I've defined an ordering for Seq[Seq[T]] such that it's a normal lexicographic ordering except all items (sub-sequences) are reversed first (so that C,B,A comes before A,B,C but after A,B,A):
implicit def ReverseListOrdering[T: Ordering] = new Ordering[Seq[T]] {
override def compare(xs1: Seq[T], xs2: Seq[T]) =
doCompare(xs1.reverse, xs2.reverse)
private def doCompare(xs1: Seq[T], xs2: Seq[T]): Int = (xs1, xs2) match {
case (Nil, Nil) => 0
case (x :: _, Nil) => 1
case (Nil, x :: _) => -1
case (x :: xs, y :: ys) =>
val a = implicitly[Ordering[T]].compare(x, y)
if (a != 0) a else doCompare(xs, ys)
}
}
This used to be defined on List[List[T]] at first but I later realized I want it for all Seq[Seq[T]]; this is why I initially left in the Nils in the pattern matching block, while failing to realize Nil never matches e.g. an empty Array.
Later I tried to run this block of code:
// the Seq[String] declarations are needed; otherwise sample` will be Array[Object] for some reason
val sample = List(
List("Estonia"): Seq[String],
Array("Tallinn", "Estonia"): Seq[String],
List("Tallinn", "Harju", "Estonia"): Seq[String])
println(sample.sorted)
This compiles just fine but results in the following error at runtime:
scala.MatchError: (WrappedArray(Estonia, Tallinn),List(Estonia)) (of class scala.Tuple2)
— while I understand the cause of the error perfectly well, what I fail to understand (or at least accept) is, if the Ordering is successfully defined on all Seq[Seq[T]], yet a superficially valid but obviously incompatible (in terms of how doCompare is defined) Seq[Seq[T]] (i.e. Array[List[String] | Array[String]]) attempt to use that ordering results in no static type errors or even warnings whatsoever.
Is this caused by the fact that the pattern matching code is not statically verified to cover all possible "instances" of Seq[Seq[T]] and that it only handles the List case? If yes, what are the currently available workarounds to achieving type safety in such cases? Is Scalaz something to be looked at yet again for a decent solution?
P.S. I'm aware I could easily do away with a solution that works for all Seq[Seq[T]] by not using pattern matching and resorting to head and tail with an if-else block (or case statements if guards, which is only superficially nicer), but I'm keen to learn how to make the most of out Scala's type capabilities (AFAIK F# and Haskell catch these errors for breakfast); not to mention pattern matching is by far more elegant and readable.
This might be closer:
scala> def cmp[A, B[_] <: Seq[_]](xs: B[A], ys: B[A]) = (xs, ys) match { case (Nil, Nil) => true }
<console>:7: error: pattern type is incompatible with expected type;
found : scala.collection.immutable.Nil.type
required: B[?A1] where type ?A1 (this is a GADT skolem)
def cmp[A, B[_] <: Seq[_]](xs: B[A], ys: B[A]) = (xs, ys) match { case (Nil, Nil) => true }
^
There is a known syndrome when the type parameter is on the class instead of the method.
It has surfaced on the ML recently. Here.
Comparing to:
scala> (null: Seq[_]) match { case _: Nil.type => true }
scala.MatchError: null
... 33 elided
scala> (null: List[_]) match { case _: Nil.type => true }
<console>:8: warning: match may not be exhaustive.
It would fail on the following input: List(_)
(null: List[_]) match { case _: Nil.type => true }
^
scala.MatchError: null
... 33 elided
scala> (null: List[_]) match { case Nil => true }
<console>:8: warning: match may not be exhaustive.
It would fail on the following input: List(_)
(null: List[_]) match { case Nil => true }
^
scala.MatchError: null
... 33 elided
Sorry to be lazy, but off to bed.
Scala compiler produces non-exhaustive match warnings only for sealed types, which Seq isn't. AFAIK, there is no way to force it to check, like there is for tail recursion.
(AFAIK F# and Haskell catch these errors for breakfast)
Haskell doesn't have an equivalent to Seq; the code you used to have with List is the one which is equivalent to Haskell (modulo laziness), and Scala does catch the error in this case. I don't know F# well, but looking at http://msdn.microsoft.com/en-us/library/dd547125.aspx it seems that pattern matching a general IEnumerable<T> isn't supported.
Use code:
implicit def ReverseListOrdering[T: Ordering] = new Ordering[Seq[T]] {
override def compare(xs1: Seq[T], xs2: Seq[T]) =
doCompare(xs1.reverse, xs2.reverse)
private def doCompare(xs1: Seq[T], xs2: Seq[T]): Int = (xs1, xs2) match {
case (Seq(), Seq()) => 0
case (x +: _, Seq()) => 1
case (Seq(), x +: _) => -1
case (x +: xs, y +: ys) =>
val a = implicitly[Ordering[T]].compare(x, y)
if (a != 0) a else doCompare(xs, ys)
}
}
As I mention is comment Nil is not the same type as Seq(). For example WrappedArray is not a List. And when you use x :: xs - it is matched as List. Array("Tallinn", "Estonia") is converted to WrappedArray. Always use +: in pattern matching when you use Seq

Liftweb - Convert List[Box[T]] into Box[List[T]]

I would like to convert a List[Box[T]] into a Box[List[T]].
I know that I could use foldRight, but I can't find an elegant way into doing so.
EDIT I would like to keep the properties of Box, that is to say, if there is any failure, return a Box with this failure.
If you only want to collect the "Full" values
I'm not sure why you'd want a Box[List[T]], because the empty list should suffice to signal the lack of any values. I'll assume that's good enough for you.
I don't have a copy of Lift handy, but I know that Box is inspired by Option and has a flatMap method, so:
Long form:
for {
box <- list
value <- box
} yield value
Shorter form:
list.flatMap(identity)
Shortest form:
list.flatten
If you want to collect the failures too:
Here's the mapSplit function I use for this kind of problem. You can easily adapt it to use Box instead of Either:
/**
* Splits the input list into a list of B's and a list of C's, depending on which type of value the mapper function returns.
*/
def mapSplit[A,B,C](in: Traversable[A])(mapper: (A) ⇒ Either[B,C]): (Seq[B], Seq[C]) = {
#tailrec
def mapSplit0(in: Traversable[A], bs: Vector[B], cs: Vector[C]): (Seq[B], Seq[C]) = {
in match {
case t if t.nonEmpty ⇒
val a = t.head
val as = t.tail
mapper(a) match {
case Left(b) ⇒ mapSplit0(as, bs :+ b, cs )
case Right(c) ⇒ mapSplit0(as, bs, cs :+ c)
}
case t ⇒
(bs, cs)
}
}
mapSplit0(in, Vector[B](), Vector[C]())
}
And when I just want to split something that's already a Seq[Either[A,B]], I use this:
/**
* Splits a List[Either[A,B]] into a List[A] from the lefts and a List[B] from the rights.
* A degenerate form of {#link #mapSplit}.
*/
def splitEither[A,B](in: Traversable[Either[A,B]]): (Seq[A], Seq[B]) = mapSplit(in)(identity)
It's really easier to do this with a tail-recursive function than with a fold:
final def flip[T](l: List[Option[T]], found: List[T] = Nil): Option[List[T]] = l match {
case Nil => if (found.isEmpty) None else Some(found.reverse)
case None :: rest => None
case Some(x) :: rest => flip(rest, x :: found)
}
This works as expected:
scala> flip(List(Some(3),Some(5),Some(2)))
res3: Option[List[Int]] = Some(List(3, 5, 2))
scala> flip(List(Some(1),None,Some(-1)))
res4: Option[List[Int]] = None
One can also do this with Iterator.iterate, but it's more awkward and slower, so I would avoid that approach in this case.
(See also my answer in the question 4e6 linked to.)