scala zip list to tuple - list

Working with JodaTime, trying to convert a List[LocalDate] to Tuple2[JodaTime, JodaTime] so I can do multi-assigment like so:
val(expire, now) =
List(row.expireDate, new JodaDate) zip (_.toDateTimeAtStartOfDay.getMillis)
which of course does not compile. Is there a similarly concise way to do the above? I know I can just do it manually:
val(expire, now) =
(row.expireDate.toDateTimeAtStartOfDay.getMillis,
new JodaDate().toDateTimeAtStartOfDay.getMillis)
but that's a bit ugly

val Seq(expire, now) =
Seq(row.expireDate, new JodaDate).map(_.toDateTimeAtStartOfDay.getMillis)

What you want (assuming you don't want to go the conversion-to-Seq route) is Scalaz's Bifunctor instance for tuples (which isn't in the standard library). With it you can write the following:
scala> import scalaz._, Scalaz._
import scalaz._
import Scalaz._
scala> val cap = (_: String).toUpperCase
cap: String => java.lang.String = <function1>
scala> val removeLs = (_: String).replaceAll("l", "")
removeLs: String => java.lang.String = <function1>
scala> cap <-: ("hello", "world") :-> removeLs
res0: (java.lang.String, java.lang.String) = (HELLO,word)
Or, in your case:
val f = (_: JodaDate).toDateTimeAtStartOfDay.getMillis
val (expire, now) = f <-: (row.expireDate, new JodaDate) :-> f

val Seq(a, b) =
Seq("a", "b").map(_.toUpperCase)
println("a, b = %s, %s".format(a, b)) // a, b = A, B

If you want to keep the type safety of using a tuple (remember, when unapplying a Seq, the compiler will not check the length), you can write a wrapper to add a function not available in the standard library, which will let you map over a tuple.
In the case of mapping over both elements using a single function, because a Tuple2[A, B] has two type parameters, the key to making this work is to require evidence that A and B are the same type. To do this, require an implicit parameter of type B =:= A; if the types are indeed equal, the compiler will supply a function of type B => A.
class Tuple2Wrapper[A, B](t: (A, B)) {
def bimap[C, D](f: A => C, g: B => D): (C, D) = (f(t._1), g(t._2))
def <-:->[C](f: A => C)(implicit ev: B =:= A): (C, C) = bimap(f, f compose ev)
}
implicit def tuple2Tuple2Wrapper[A, B](t: (A, B)) = new Tuple2Wrapper(t)
scala> (1, 1) <-:-> (_ + 1)
res1: (Int, Int) = (2,2)
This could be done in a more general and useful way (applicable to more types than just Tuple2), if implemented in terms of Scalaz's Bifunctor trait.

Related

ZipList with Scalaz

Suppose I have a list of numbers and list of functions:
val xs: List[Int] = List(1, 2, 3)
val fs: List[Int => Int] = List(f1, f2, f3)
Now I would like to use an Applicative to apply f1 to 1, f2 to 2, etc.
val ys: List[Int] = xs <*> fs // expect List(f1(1), f2(2), f3(3))
How can I do it with Scalaz ?
pure for zip lists repeats the value forever, so it's not possible to define a zippy applicative instance for Scala's List (or for anything like lists). Scalaz does provide a Zip tag for Stream and the appropriate zippy applicative instance, but as far as I know it's still pretty broken. For example, this won't work (but should):
import scalaz._, Scalaz._
val xs = Tags.Zip(Stream(1, 2, 3))
val fs = Tags.Zip(Stream[Int => Int](_ + 3, _ + 2, _ + 1))
xs <*> fs
You can use the applicative instance directly (as in the other answer), but it's nice to have the syntax, and it's not too hard to write a "real" (i.e. not tagged) wrapper. Here's the workaround I've used, for example:
case class ZipList[A](s: Stream[A])
import scalaz._, Scalaz._, Isomorphism._
implicit val zipListApplicative: Applicative[ZipList] =
new IsomorphismApplicative[ZipList, ({ type L[x] = Stream[x] ## Tags.Zip })#L] {
val iso =
new IsoFunctorTemplate[ZipList, ({ type L[x] = Stream[x] ## Tags.Zip })#L] {
def to[A](fa: ZipList[A]) = Tags.Zip(fa.s)
def from[A](ga: Stream[A] ## Tags.Zip) = ZipList(Tag.unwrap(ga))
}
val G = streamZipApplicative
}
And then:
scala> val xs = ZipList(Stream(1, 2, 3))
xs: ZipList[Int] = ZipList(Stream(1, ?))
scala> val fs = ZipList(Stream[Int => Int](_ + 10, _ + 11, _ + 12))
fs: ZipList[Int => Int] = ZipList(Stream(<function1>, ?))
scala> xs <*> fs
res0: ZipList[Int] = ZipList(Stream(11, ?))
scala> res0.s.toList
res1: List[Int] = List(11, 13, 15)
For what it's worth, it looks like this has been broken for at least a couple of years.
I see a solution with streamZipApplicative :
import scalaz.std.stream._
import scalaz.Tags
val xs: List[Int] = List(1, 2, 3)
val fs: List[Int => Int] = List(f1, f2, f3)
val zippedLists = streamZipApplicative.ap(Tags.Zip(xs.toStream)) (Tags.Zip(fs.toStream))
val result = Tag.unwrap(zippedLists).toList
Learning Scalaz spends a few paragraphs on this topic in their introduction to Applicatives. They quote LYAHFGG:
However, [(+3),(2)] <> [1,2] could also work in such a way that the first function in the left list gets applied to the first value in the right one, the second function gets applied to the second value, and so on. That would result in a list with two values, namely [4,4]. You could look at it as [1 + 3, 2 * 2].
But then adds:
This can be done in Scalaz, but not easily.
The "not easily" part uses streamZipApplicative like in #n1r3's answer:
scala> streamZipApplicative.ap(Tags.Zip(Stream(1, 2)))(Tags.Zip(Stream({(_: Int) + 3}, {(_: Int) * 2})))
res32: scala.collection.immutable.Stream[Int] with Object{type Tag = scalaz.Tags.Zip} = Stream(4, ?)
scala> res32.toList
res33: List[Int] = List(4, 4)
The "not easily" is the part that bothers me. I'd like to borrow from #Travis Brown fantastic answer. He is comparing the use of monads and applicatives (i.e. why use applicatives when you have a monad?):
Second (and relatedly), it's just a solid development practice to use the least powerful abstraction that will get the job done.
So, I would say that until a framework provides an applicative that works like your first use-case:
val ys: List[Int] = xs <*> fs
To use zip and map here instead:
xs.zip(fs).map(p=>p._2.apply(p._1))
To me, this code is much clearer and simpler than the alternatives in scalaz. This is the least powerful abstraction that gets the job done.

Zipping two lists into a single list of objects rather than a list of tuples?

val l1 = List(1, 2, 3)
val l2 = List('a', 'b', 'c')
val tupleList = l1.zip(l2)
// List((1,a), (2,b), (3,c))
val objectList = l1.zip(l2).map(tuple => new MyObject(tuple._1, tuple._2))
// List(MyObject#7e1a1da6, MyObject#5f7f2382, MyObject#407cf41)
After writing this code, I feel like the map(tuple => new MyObject(tuple._1, tuple._2)) part looks a little dirty for two reasons:
I shouldn't be creating the tuples just to discard them in favor of MyObject. Why not just zip l1 and l2 into a list of MyObject in the first place?
tuple._1 and tuple._2 don't have any semantics. It can take some mental gymnastics to make sure I'm giving the Int as the first parameter and the Char as the second.
Is it possible to zip two Lists into my own object?
How can I make the MyObject construction above more semantically clear?
scala> case class Foo(i: Int, c: Char)
defined class Foo
scala> val f = Foo.apply _
f: (Int, Char) => Foo = <function2>
scala> (l1, l2).zipped map f
res12: List[Foo] = List(Foo(1,a), Foo(2,b), Foo(3,c))
More info, since someone didn't get what I meant, here's what this map looks like:
https://github.com/scala/scala/blob/2.11.x/src/library/scala/runtime/Tuple2Zipped.scala#L35
If you want a self made implementation for your problem, you can do something similar to what I did below. (wasted my time with)
There is already one implemented method to do that, which is described in #som-snytt 's answer.
An example implementation for your problem, which does not create intermediate tuples.
def createObjects[A,B,C](func: (A,B) => C)(l1: List[A], l2: List[B]) = {
val resultBuffer = new ListBuffer[C]
#tailrec
def loop(l1: List[A], l2: List[B]): Unit = l1 match {
case head :: tail if l2.headOption.isDefined => {
resultBuffer += func(l1.head, l2.head)
loop(l1.tail, l2.tail)
}
case Nil =>
}
loop(l1, l2)
resultBuffer.result
}
You can then use it like this:
createObjects(MyObject)(l1, l2)
createObjects(MyObject)(l1, l2) only works if MyObject is a case class or has an apply method.
In the other case you can do one of the following:
createObjects[Int, Char, MyObject](new MyObject(_,_))(l1, l2)
createObjects((i: Int, c: Char) => new MyObject(i,c))(l1, l2)
A slightly cleaner version using pattern matching would help with #2:
val objectList = (l1 zip l2).map { case (a, b) => new MyObject(a,b) }
A more extreme version would be to use a factory method on a companion class that turned the tuple into an instance of MyClass.
object MyClass {
def make(t: (Int, Char)) = new MyClass(t._1, t._2)
}
val objs = (l1 zip l2).map(MyClass.make)
You could even get fancier by making the companion object a function to further reduce the clutter:
object MyClass extends (Tuple2[Int, Char] => MyClass) {
def apply(t: (Int, Char)) = new MyClass(t._1, t._2)
}
val objs = (l1 zip l2).map(MyClass)

Convert a Scala list to a tuple?

How can I convert a list with (say) 3 elements into a tuple of size 3?
For example, let's say I have val x = List(1, 2, 3) and I want to convert this into (1, 2, 3). How can I do this?
You can do it using scala extractors and pattern matching (link):
val x = List(1, 2, 3)
val t = x match {
case List(a, b, c) => (a, b, c)
}
Which returns a tuple
t: (Int, Int, Int) = (1,2,3)
Also, you can use a wildcard operator if not sure about a size of the List
val t = x match {
case List(a, b, c, _*) => (a, b, c)
}
You can't do this in a typesafe way. Why? Because in general we can't know the length of a list until runtime. But the "length" of a tuple must be encoded in its type, and hence known at compile time. For example, (1,'a',true) has the type (Int, Char, Boolean), which is sugar for Tuple3[Int, Char, Boolean]. The reason tuples have this restriction is that they need to be able to handle a non-homogeneous types.
an example using shapeless :
import shapeless._
import syntax.std.traversable._
val x = List(1, 2, 3)
val xHList = x.toHList[Int::Int::Int::HNil]
val t = xHList.get.tupled
Note: the compiler need some type informations to convert the List in the HList that the reason why you need to pass type informations to the toHList method
Shapeless 2.0 changed some syntax. Here's the updated solution using shapeless.
import shapeless._
import HList._
import syntax.std.traversable._
val x = List(1, 2, 3)
val y = x.toHList[Int::Int::Int::HNil]
val z = y.get.tupled
The main issue being that the type for .toHList has to be specified ahead of time. More generally, since tuples are limited in their arity, the design of your software might be better served by a different solution.
Still, if you are creating a list statically, consider a solution like this one, also using shapeless. Here, we create an HList directly and the type is available at compile time. Remember that an HList has features from both List and Tuple types. i.e. it can have elements with different types like a Tuple and can be mapped over among other operations like standard collections. HLists take a little while to get used to though so tread slowly if you are new.
scala> import shapeless._
import shapeless._
scala> import HList._
import HList._
scala> val hlist = "z" :: 6 :: "b" :: true :: HNil
hlist: shapeless.::[String,shapeless.::[Int,shapeless.::[String,shapeless.::[Boolean,shapeless.HNil]]]] = z :: 6 :: b :: true :: HNil
scala> val tup = hlist.tupled
tup: (String, Int, String, Boolean) = (z,6,b,true)
scala> tup
res0: (String, Int, String, Boolean) = (z,6,b,true)
Despite the simplicity and being not for lists of any length, it is type-safe and the answer in most cases:
val list = List('a','b')
val tuple = list(0) -> list(1)
val list = List('a','b','c')
val tuple = (list(0), list(1), list(2))
Another possibility, when you don't want to name the list nor to repeat it (I hope someone can show a way to avoid the Seq/head parts):
val tuple = Seq(List('a','b')).map(tup => tup(0) -> tup(1)).head
val tuple = Seq(List('a','b','c')).map(tup => (tup(0), tup(1), tup(2))).head
FWIW, I wanted a tuple to initalise a number of fields and wanted to use the syntactic sugar of tuple assignment.
EG:
val (c1, c2, c3) = listToTuple(myList)
It turns out that there is syntactic sugar for assigning the contents of a list too...
val c1 :: c2 :: c3 :: Nil = myList
So no need for tuples if you've got the same problem.
If you are very sure that your list.size<23 use it:
def listToTuple[A <: Object](list:List[A]):Product = {
val class = Class.forName("scala.Tuple" + list.size)
class.getConstructors.apply(0).newInstance(list:_*).asInstanceOf[Product]
}
listToTuple: [A <: java.lang.Object](list: List[A])Product
scala> listToTuple(List("Scala", "Smart"))
res15: Product = (Scala,Smart)
You can't do this in a type-safe way. In Scala, lists are arbitrary-length sequences of elements of some type. As far as the type system knows, x could be a list of arbitrary length.
In contrast, the arity of a tuple must be known at compile time. It would violate the safety guarantees of the type system to allow assigning x to a tuple type.
In fact, for technical reasons, Scala tuples were limited to 22 elements, but the limit no longer exists in 2.11 The case class limit has been lifted in 2.11 https://github.com/scala/scala/pull/2305
It would be possible to manually code a function that converts lists of up to 22 elements, and throws an exception for larger lists. Scala's template support, an upcoming feature, would make this more concise. But this would be an ugly hack.
This can also be done in shapeless with less boilerplate using Sized:
scala> import shapeless._
scala> import shapeless.syntax.sized._
scala> val x = List(1, 2, 3)
x: List[Int] = List(1, 2, 3)
scala> x.sized(3).map(_.tupled)
res1: Option[(Int, Int, Int)] = Some((1,2,3))
It's type-safe: you get None, if the tuple size is incorrect, but the tuple size must be a literal or final val (to be convertible to shapeless.Nat).
Using Pattern Matching:
val intTuple = List(1,2,3) match {case List(a, b, c) => (a, b, c)}
2015 post.
For the Tom Crockett's answer to be more clarifying, here is a real example.
At first, I got confused about it. Because I come from Python, where you can just do tuple(list(1,2,3)).
Is it short of Scala language ? (the answer is -- it's not about Scala or Python, it's about static-type and dynamic-type.)
That's causes me trying to find the crux why Scala can't do this .
The following code example implements a toTuple method, which has type-safe toTupleN and type-unsafe toTuple.
The toTuple method get the type-length information at run-time, i.e no type-length information at compile-time, so the return type is Product which is very like the Python's tuple indeed (no type at each position, and no length of types).
That way is proned to runtime error like type-mismatch or IndexOutOfBoundException. (so Python's convenient list-to-tuple is not free lunch. )
Contrarily , it is the length information user provided that makes toTupleN compile-time safe.
implicit class EnrichedWithToTuple[A](elements: Seq[A]) {
def toTuple: Product = elements.length match {
case 2 => toTuple2
case 3 => toTuple3
}
def toTuple2 = elements match {case Seq(a, b) => (a, b) }
def toTuple3 = elements match {case Seq(a, b, c) => (a, b, c) }
}
val product = List(1, 2, 3).toTuple
product.productElement(5) //runtime IndexOutOfBoundException, Bad !
val tuple = List(1, 2, 3).toTuple3
tuple._5 //compiler error, Good!
you can do this either
via pattern-matching (what you do not want) or
by iterating through the list and applying each element one by one.
val xs: Seq[Any] = List(1:Int, 2.0:Double, "3":String)
val t: (Int,Double,String) = xs.foldLeft((Tuple3[Int,Double,String] _).curried:Any)({
case (f,x) => f.asInstanceOf[Any=>Any](x)
}).asInstanceOf[(Int,Double,String)]
In scala 3, you can do something like this:
def totuple[A](as: List[A]): Tuple = as match
case Nil => EmptyTuple
case h :: t => h *: totuple(t)
but as has been said already, without giving the compiler any more hard-coded type information, you aren't going to know the length of the tuple or the types of its elements, so this is likely hardly any better than the original list.
as far as you have the type:
val x: List[Int] = List(1, 2, 3)
def doSomething(a:Int *)
doSomething(x:_*)

Deep-reverse of nested lists in Scala

I'd like to reverse a list of lists, recursively, in Scala.
I've written deep list reverses in Python like this:
def deepReverse(items):
if type(items) == list:
return [deepReverse(item) for item in reversed(items)]
else:
return items
How would I do the equivalent in Scala? The problem isn't the algorithm - it's the type stuff, which I'm newer on.
I need the function to take a list of [T], or a List[List[T]], or a list of T's and lists of Ts, to any arbitrary depth. I tried making a case class to do that based on an example I'd seen elsewhere. I don't want a function that just returns Any and accepts Any; that feels like cheating.
case class NL[+T](val v : Either[List[NL[T]],T])
Still, I couldn't quite get my types to balance out. I'm new to Scala, but I figured it'd be a perfect opportunity to mess with recursion and typing.
It's actually not too hard to write a version of the type class approach that sschaef proposes that will work for arbitrarily nested lists:
trait Reverser[C] {
def reverse(xs: C): C
}
implicit def rev[A](implicit ev: Reverser[A] = null) = new Reverser[List[A]] {
def reverse(xs: List[A]) =
Option(ev).map(r => xs map r.reverse).getOrElse(xs).reverse
}
def deepReverse[A](xs: A)(implicit ev: Reverser[A]): A = ev.reverse(xs)
The implicit argument ev in our rev method is evidence that A itself is reversable, and if ev is null that means it's not. If we have this evidence that A is reversable, we use it to reverse the elements of our List[A] (this is what the map is doing), and then we reverse the list itself. If we don't have this evidence (the getOrElse case), we can just reverse the list.
We could write rev a little less concisely (but possibly more performantly) like this:
implicit def rev[A](implicit ev: Reverser[A] = null) = if (ev == null) {
new Reverser[List[A]] {
def reverse(xs: List[A]) = xs.reverse
}
} else {
new Reverser[List[A]] {
def reverse(xs: List[A]) = (xs map ev.reverse).reverse
}
}
To test either of these two versions, we can write the following:
scala> deepReverse(List.tabulate(3)(identity))
res0: List[Int] = List(2, 1, 0)
scala> deepReverse(List.tabulate(2,3) { case (a, b) => a + b })
res1: List[List[Int]] = List(List(3, 2, 1), List(2, 1, 0))
scala> deepReverse(List.tabulate(2, 3, 4, 5, 6) {
| case (a, b, c, d, e) => a + b + c + d + e
| }).head.head.head.head
res2: List[Int] = List(15, 14, 13, 12, 11, 10)
As expected.
I should add that the following is a more common idiom for getting the implicits right in a case like this:
trait ReverserLow {
implicit def listReverser[A] = new Reverser[List[A]] {
def reverse(xs: List[A]) = xs.reverse
}
}
object ReverserHigh extends ReverserLow {
implicit def nestedListReverser[A](implicit ev: Reverser[A]) =
new Reverser[List[A]] {
def reverse(xs: List[A]) = xs.map(ev.reverse).reverse
}
}
import ReverserHigh._
If we'd just written listReverser and nestedListReverser at the same level, we'd get the following error when we try to reverse a list of lists:
scala> deepReverse(List.tabulate(2, 3)(_ + _))
<console>:12: error: ambiguous implicit values:
both method listReverser...
and method nestedListReverser...
match expected type Reverser[List[List[Int]]]
deepReverse(List.tabulate(2, 3)(_ + _))
The standard approach to prioritizing the two is to put the lower priority implicit in a trait (WhateverLow) and the other in an object (WhateverHigh) that extends that trait. In a fairly simple case like this, though, it's more concise (and clearer, to my eye) to use the default argument trick in my rev method above. But you're more likely to see the other version in other people's code.
If you wanna have this really typesafe then the typeclass pattern is your friend:
object Reverse extends App {
trait Reverser[C] {
def reverse(xs: C): C
}
implicit def List1Reverser[A] = new Reverser[List[A]] {
def reverse(xs: List[A]) =
xs.reverse
}
implicit def List2Reverser[A] = new Reverser[List[List[A]]] {
def reverse(xs: List[List[A]]) =
xs.map(_.reverse).reverse
}
implicit def List3Reverser[A] = new Reverser[List[List[List[A]]]] {
def reverse(xs: List[List[List[A]]]) =
xs.map(_.map(_.reverse).reverse).reverse
}
def deepReverse[A](xs: A)(implicit rev: Reverser[A]): A =
rev.reverse(xs)
val xs = List(1,2)
val xxs = List(List(1,2),List(1,2),List(1,2))
val xxxs = List(List(List(1,2),List(1,2)),List(List(1,2),List(1,2)),List(List(1,2),List(1,2)))
println(deepReverse(xs))
println(deepReverse(xxs))
println(deepReverse(xxxs))
}
The only problem with this is that you need a typeclass for each nested list type.

Scala extending the List class with a coalesce preappend method

Im attempting to create a new operator :? on lists, which operates the same as :: except if the value if null, then the original list is returned. I have written the following, however it soon dawned that I didn't really know what I was doing....
object ImplicitList {
implicit def extendIterator[T](i : List[T]) = new ListExtension(i)
}
class ListExtension[T <: Any](i : List[T]) {
def :?[B >: T] (x: B): List[B] = if (x != null) x :: i else i
}
final case class :?[B](private val hd: B, private val tl: ListExtension[B]) extends ListExtension[B](tl.:?(hd))
What you want is the enhance-my-library pattern. With this you can add a new method to List. Here's how that would look:
class EnhancedList[T](self: List[T]) {
def ?:(t: T) =
t match {
case null => self
case _ => t :: self
}
}
implicit def enhanceList[T](self: List[T]) = new EnhancedList(self)
So there's a class EnhancedList that wraps List where the new method ?: is defined, and an implicit function that converts List to EnhancedList when ?: is called. Note that you have to use ?: instead of :? because Scala's rules are such that an operator is right-associative if and only if it ends in a :.
Here's how it gets used:
scala> val l = List("a","b","c")
l: List[java.lang.String] = List(a, b, c)
scala> null ?: l
res136: List[java.lang.String] = List(a, b, c)
scala> "d" ?: l
res137: List[java.lang.String] = List(d, a, b, c)