I would like to pattern match
on different segments of a list
in scala
on the types of the head
and tail
:
class Solution07 extends FlatSpec with ShouldMatchers {
"plain recursive flatten" should "flatten a list" in {
val list1 = List(List(1, 1), 2, List(3, List(5, 8)))
val list1Flattened = List(1, 1, 2, 3, 5, 8)
flattenRecur(list1) should be (list1Flattened)
}
def flattenRecur(ls: List[Any]): List[Int] = ls match {
case (head: Int) :: (tail: List[Any]) => head :: flattenRecur(tail)
case (head: List[Int]) :: (tail: List[Any]) => head.head :: flattenRecur(head.tail :: tail)
case (head: List[Any]) :: (tail: List[Any]) => flattenRecur(head) :: flattenRecur(tail) // non-variable type... on this line.
}
}
I get:
Error:(18, 17) non-variable type argument Int in type pattern List[Int] (the underlying of List[Int]) is unchecked since it is eliminated by erasure case (head: List[Int]) :: (tail: List[Any]) => head.head :: flattenRecur(head.tail :: tail) ^
What am I missing? how is it possible for me to pattern match on the head
and tail
's types of the list?
Notes. Scala's pattern matching statement is most useful for matching on algebraic types expressed via case classes. Scala also allows the definition of patterns independently of case classes, using unapply methods in extractor objects.
Pattern matching is a way of checking the given sequence of tokens for the presence of the specific pattern. It is the most widely used feature in Scala. It is a technique for checking a value against a pattern. It is similar to the switch statement of Java and C.
It is defined in Scala's root class Any and therefore is available for all objects. The match method takes a number of cases as an argument. Each alternative takes a pattern and one or more expressions that will be performed if the pattern matches. A symbol => is used to separate the pattern from the expressions.
I agree that @Andreas solution with HList is a nice example for solving the problem, but I still do not understand what's the problem with this:
def flatten(ls: List[_]): List[Int] = ls match {
case Nil => Nil
case (a: Int) :: tail => a :: flatten(tail)
case (a: List[_]) :: tail => flatten(a) ::: flatten(tail)
case _ :: tail => flatten(tail)
}
Then:
println(flatten(List(List("one",9,8),3,"str",4,List(true,77,3.2)))) // List(9, 8, 3, 4, 77)
I don't see any problems with type erasure in your task, because you actually don't need to test the types that are erased. I've intentionally skipped all erased types in my example - to show this. Type erasure does not clear the type information of the elements of the list, it clears only the type information of list generic which you have Any
or _
in my case - so you do not need that at all. If I am not missing someting, in your example the types are not erased at all, because you anyway have Any
almost everywhere.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With