This question already has answers here:
Generic Programming in Scala
(2 answers)
Closed 8 years ago.
I am writing a parameterized merge sort functionality and passing the less checker as a function.
However, the compiler is throwing following error.
type mismatch;
found : y.type (with underlying type T)
required: T
Here is my full code
def mergeSort[T] (list:List[T], pred:(T,T) =>Boolean):List[T]={
def merge[T](left:List[T], right:List[T], acc:List[T]):List[T] = (left,right) match{
case (Nil,_) => acc ++ right
case (_,Nil) => acc ++ left
case (x::xs, y::ys) => if(pred(y,x)) merge(left,ys,acc :+ y) else merge(xs,right,acc :+ x)
}
val m = list.length/2
if (m == 0) list
else {
val (l,r) = list splitAt m
merge(mergeSort(l,pred), mergeSort(r,pred), List())
}
}
The problem is at line
if(pred(y,x))
Everything seems logically correct, can't figure out why this is happening?
help appreciated.
This happens because in your inner function merge you define a type T, it's like you're redefining the one you created in mergeSort. Just change def merge[T] to def merge and keep using T to parameterized your lists left, right, etc. That way you are telling the compiler "This is the same T I defined above in mergeSort".
Related
This question already has answers here:
List[Try[T]] to Try[List[T]] in Scala
(4 answers)
Closed 1 year ago.
Suppose I have a List of tries in scala, for example: List(Try(a), Try(b), Try(c)).
If want to write a code snippets that returns Success(List(a, b, c)) if all tries are successes, and returns a Failure if one of the tries is a failure.
The only way I found to do it is:
private def convertArrayOfSuccessesToSuccessOfByteArray(
tryArrayForOutput: Array[Try[Byte]]
): Success[Array[Byte]] = {
val outputArray = ArrayBuffer[Byte]()
tryArrayForOutput.foreach(tryElem => {
val Success(elem) = tryElem
outputArray.append(elem)
})
Success(outputArray.toArray)
}
As you can see, it's pretty cumbersome and not so "functional".
Just get each value and wrap in a Try to catch the first error, if any
Try(tryArrayForOutput.map(_.get))
#Tim's answer is good in this case.
One more general functional way would be to fold and flatMap:
private def convertArrayOfSuccessesToSuccessOfByteArray(tryArrayForOutput: Seq[Try[Byte]]): Try[Seq[Byte]] = {
tryArrayForOutput.foldLeft(Try(Seq[Byte]())) { (acc: Try[Seq[Byte]], t: Try[Byte]) =>
acc.flatMap { seq: Seq[Byte] =>
t.map((b: Byte) => seq :+ b)
}
}
}
This can be generalised and is typically a method provided by libraries like Cats.
This question already has answers here:
Understanding type Parameters in Scala
(1 answer)
Scala type parameters in various places
(2 answers)
Closed 4 years ago.
I am newly learning Scala. below code has [A] multiple times. Please, someone, explain me in layman terms. I am unable to understand(tried google and read StackOverflow and others answers but I don't get it. The code below is to find kth element from the list.
def findKth[A](k:Int, l:List[A]):A = k match {
case 0 => l.head
case k if k > 0 => findKth(k - 1, l.tail)
case _ => throw new NoSuchElementException
}
def findKth[A](k:Int, l:List[A]):A = k match {
case 0 => l.head
case k if k > 0 => findKth(k - 1, l.tail)
case _ => throw new NoSuchElementException
}
Here [A] is the type parameter for function findKth. Now what does type parameter mean?
Type parameter tells the compiler that method findKth can take parameter of type A. Which is the generic type here because A can be anything. For example A can be Int, Double, another List -- anything.
For more information I would suggest you to go through these links:
https://docs.scala-lang.org/tour/polymorphic-methods.html
https://docs.scala-lang.org/tour/generic-classes.html
It is for declaring generic parameters in Scala, You can call your method with a list of different types (Double, Int, Dogs ... )
If you want to learn more, this post: https://apiumhub.com/tech-blog-barcelona/scala-type-bounds/
For example:
def findKth[A](k:Int, l:List[A]):A = k match {
case 0 => l.head
case k if k > 0 => findKth(k - 1, l.tail)
case _ => throw new NoSuchElementException
}
val intList = 1 :: 2::3::4::5::6::7::8::9::10::Nil
val strList = intList.map(_.toString)
println(findKth(9, intList))
println(findKth(3, strList))
As you can see, you can pass to your function a List[Int], or a List[String], it is a way to parametrize functions to accept generics arguments.
You can see it working in here: https://scalafiddle.io/sf/XwaALIk/0
def flatten(l: List[_]): List[_] = {
def iflatten(l: List[_], ret: List[_]): List[_] = l match {
case Nil => ret
case h :: Nil =>
if( h.isInstanceOf[List[_]]) { iflatten(h, ret) }
else {
l.head :: ret
iflatten(l.tail, ret)
}
}
}
I know there are multiple ways to do this, and I'm not 100% sure my way is correct. I would like to test it but one issue I'm running into is in the second case statement where I call:
... { iflatten(h, ret) }
I am getting the compiler error:
error: type mismatch;
found : Unit
required: List[?]
I'm trying to work through these type issues to learn more about the typesystem as it's different than what I've worked with in the past. Any suggestions as to why the compiler is complaining would be greatly appreciated.
I'm not getting the same error you are concerning iflatten(h,ret).
I am getting the found : Unit; required : List[?] error, but it refers to the fact that you are not calling iflatten in flatten itself : after defining it, you need to call the function at the end of flatten's definition.
def flatten(l: List[_]): List[_] = {
def iflatten(l: List[_], ret: List[_]): List[_] = l match {
case Nil => ret
case (h:List[_]) :: tail => iflatten(tail,iflatten(h,ret))
case h :: tail => iflatten(tail,h::ret)
}
iflatten(l,List()).reverse
}
As for the code itself, you can (and should) verify types when matching.
Also note that the case h :: Nil only matches 1-length list.
As for the algorithm, you need to call iflatten within itself (that's where the arbitrarily nesting takes place).
I think you're just missing a cast.
if( h.isInstanceOf[List[_]]) { iflatten(h.asInstanceOf[List[_]], ret) }
Alternately: It would be prettier with pattern matching.
h match {
case hList: List[_] =>
iflatten(hList, ret)
case _ =>
l.head :: ret
iflatten(l.tail, ret)
}
(caveat: This is just off the top of my head and I haven't put anything through a compiler)
edit - Marth's solution of merging that into the previous pattern match looks better than mine.
Actually, I suspect the problem lies in the fact that you define the inner method iflatten, but never call it, so that the outer method flatten doesn't return anything (ie defaults to a return type of Unit, conflicting with the stated return type of List[_]).
Try adding the following as the last line of the outer flatten method:
iflatten(l, Nil)
Beyond that, you have various other problems with your code, such as not handling all match cases: you handle the case of a list with one element - h :: Nil - but not several elements. You probably meant something like h :: theRest, and then use theRest somewhere - probably as your ret parameter for the recursive call.
You also use the check h.isInstanceOf[List[_]] (generally any use of isInstanceOf is a bad code smell in scala) but then try passing h into iflatten recursively without casting it as List[_] (for example, as in #ChristopherMartin's answer, although using asInstanceOf is an even bigger code smell). #Marth's answer gives a good example of how to avoid these explicit type checks.
I think this is something the Shapeless library is good at.
https://github.com/milessabin/shapeless/blob/master/examples/src/main/scala/shapeless/examples/flatten.scala
Sorry, but this code is very complicated. I tried to simplify it and got to this solution:
scala> :paste
// Entering paste mode (ctrl-D to finish)
def flatten(l : List[_]) : List[_] = l flatMap {
case l1 : List[_] => flatten(l1)
case otherwise => List(otherwise)
}
// Exiting paste mode, now interpreting.
flatten: (l: List[_])List[_]
scala> flatten(List(1,2,3))
res3: List[Any] = List(1, 2, 3)
scala> flatten(List(1,2,List(3,4)))
res4: List[Any] = List(1, 2, 3, 4)
scala> flatten(List(List(1,List(2),3),4,List(4,5)))
res5: List[Any] = List(1, 2, 3, 4, 4, 5)
After fixing the code (adding the call to iflat), I did the following refactorings:
Removed the inner method
Used the built in flatMap for the iteration (and hence could eliminate or simplify some case expressions)
Replaced the instanceOf with type guards
I think a simpler solution would be using the shapeless library (hint: look for the "boilerplate" part).
I am going through a book Lift in action and I encountered something I don't quite understand: _ ::
object permanent_link extends MappedString(this, 150){
override def validations =
valMinLen(3, "Link URL must be at least 5 characters") _ ::
super.validations
}
I can't find any hint so I would be grateful if anyone could help me out..
I don't know Lift, but this is a general question. First of all, the :: is a Scala cons operator:
scala> 1 :: 2 :: List(3, 4)
res0: List[Int] = List(1, 2, 3, 4)
This means that super.validations is some sort of a sequence and valMinLen(3, "Link URL must be at least 5 characters") _ is a single value in that list.
From the context it looks obvious that in overridden validations method they are calling super version and prepend some extra validation at the beginning.
This extra validation is created by a call to valMinLen(). However this extra call does not return an element matching the type of validations list - but a function. Instead of prepending the function value we are explicitly saying (by adding _ suffix`) that we want to prepend a function itself, not a return value of that function.
Code snippet is worth a thousand words:
scala> def f = 3
f: Int
scala> def g = 4
g: Int
scala> val listOfInts = List(f, g)
listOfInts: List[Int] = List(3, 4)
scala> val listOfFunctions = List(f _, g _)
listOfFunctions: List[() => Int] = List(<function0>, <function0>)
Compare the type of listOfInts and listOfFunctions. I believe the f _ syntax is called partially applied function in Scala world.
The underscore ignifies that valMinLen isn't to be called but be used as a function "pointer".
The :: operator concatenates lists.
It would in other words seem like the code builds a list validations that consist of a function "pointer" to valMinLen with the parameters given and the rest of the list is the value of super.validations, that is the super class' validations.
I'm sure someone will correct my terminology here :)
The code might be more readable with some proper indentation and introducing a val:
object permanent_link extends MappedString(this, 150) {
override def validations = minimumValidation :: super.validations
val minimumValidation = valMinLen(3,"Link URL must be at least 5 characters") _
}
So as noted before, the :: operator just prepends a new element to a list, the _ has nothing to do with it and is used to obtain a function object, like in
(1 :: 2 :: Nil) map (println _)
which makes a list [1, 2] and applies the function println to every element (the underscore can actually be omitted here). The object println _ constructs a function object from the println method with the _ representing the function's single parameter.
I have a recursive function that takes a Map as single parameter. It then adds new entries to that Map and calls itself with this larger Map. Please ignore the return values for now. The function isn't finished yet. Here's the code:
def breadthFirstHelper( found: Map[AIS_State,(Option[AIS_State], Int)] ): List[AIS_State] = {
val extension =
for(
(s, v) <- found;
next <- this.expand(s) if (! (found contains next) )
) yield (next -> (Some(s), 0))
if ( extension.exists( (s -> (p,c)) => this.isGoal( s ) ) )
List(this.getStart)
else
breadthFirstHelper( found ++ extension )
}
In extension are the new entries that shall get added to the map. Note that the for-statement generates an iterable, not a map. But those entries shall later get added to the original map for the recursive call. In the break condition, I need to test whether a certain value has been generated inside extension. I try to do this by using the exists method on extension. But the syntax for extracting values from the map entries (the stuff following the yield) doesn't work.
Questions:
How do I get my break condition (the boolean statement to the if) to work?
Is it a good idea to do recursive work on a immutable Map like this? Is this good functional style?
When using a pattern-match (e.g. against a Tuple2) in a function, you need to use braces {} and the case statement.
if (extension.exists { case (s,_) => isGoal(s) } )
The above also uses the fact that it is more clear when matching to use the wildcard _ for any allowable value (which you subsequently do not care about). The case xyz gets compiled into a PartialFunction which in turn extends from Function1 and hence can be used as an argument to the exists method.
As for the style, I am not functional programming expert but this seems like it will be compiled into a iterative form (i.e. it's tail-recursive) by scalac. There's nothing which says "recursion with Maps is bad" so why not?
Note that -> is a method on Any (via implicit conversion) which creates a Tuple2 - it is not a case class like :: or ! and hence cannot be used in a case pattern match statement. This is because:
val l: List[String] = Nil
l match {
case x :: xs =>
}
Is really shorthand/sugar for
case ::(x, xs) =>
Similarly a ! b is equivalent to !(a, b). Of course, you may have written your own case class ->...
Note2: as Daniel says below, you cannot in any case use a pattern-match in a function definition; so while the above partial function is valid, the following function is not:
(x :: xs) =>
This is a bit convoluted for me to follow, whatever Oxbow Lakes might think.
I'd like first to clarify one point: there is no break condition in for-comprehensions. They are not loops like C's (or Java's) for.
What an if in a for-comprehension means is a guard. For instance, let's say I do this:
for {i <- 1 to 10
j <- 1 to 10
if i != j
} yield (i, j)
The loop isn't "stopped" when the condition is false. It simply skips the iterations for which that condition is false, and proceed with the true ones. Here is another example:
for {i <- 1 to 10
j <- 1 to 10
if i % 2 != 0
} yield (i, j)
You said you don't have side-effects, so I can skip a whole chapter about side effects and guards on for-comprehensions. On the other hand, reading a blog post I made recently on Strict Ranges is not a bad idea.
So... give up on break conditions. They can be made to work, but they are not functional. Try to rephrase the problem in a more functional way, and the need for a break condition will be replaced by something else.
Next, Oxbow is correct in that (s -> (p,c) => isn't allowed because there is no extractor defined on an object called ->, but, alas, even (a :: b) => would not be allowed, because there is no pattern matching going on in functional literal parameter declaration. You must simply state the parameters on the left side of =>, without doing any kind of decomposition. You may, however, do this:
if ( extension.exists( t => val (s, (p,c)) = t; this.isGoal( s ) ) )
Note that I replaced -> with ,. This works because a -> b is a syntactic sugar for (a, b), which is, itself, a syntactic sugar for Tuple2(a, b). As you don't use neither p nor c, this works too:
if ( extension.exists( t => val (s, _) = t; this.isGoal( s ) ) )
Finally, your recursive code is perfectly fine, though probably not optimized for tail-recursion. For that, you either make your method final, or you make the recursive function private to the method. Like this:
final def breadthFirstHelper
or
def breadthFirstHelper(...) {
def myRecursiveBreadthFirstHelper(...) { ... }
myRecursiveBreadthFirstHelper(...)
}
On Scala 2.8 there is an annotation called #TailRec which will tell you if the function can be made tail recursive or not. And, in fact, it seems there will be a flag to display warnings about functions that could be made tail-recursive if slightly changed, such as above.
EDIT
Regarding Oxbow's solution using case, that's a function or partial function literal. It's type will depend on what the inference requires. In that case, because that's that exists takes, a function. However, one must be careful to ensure that there will always be a match, otherwise you get an exception. For example:
scala> List(1, 'c') exists { case _: Int => true }
res0: Boolean = true
scala> List(1, 'c') exists { case _: String => true }
scala.MatchError: 1
at $anonfun$1.apply(<console>:5)
... (stack trace elided)
scala> List(1, 'c') exists { case _: String => true; case _ => false }
res3: Boolean = false
scala> ({ case _: Int => true } : PartialFunction[AnyRef,Boolean])
res5: PartialFunction[AnyRef,Boolean] = <function1>
scala> ({ case _: Int => true } : Function1[Int, Boolean])
res6: (Int) => Boolean = <function1>
EDIT 2
The solution Oxbow proposes does use pattern matching, because it is based on function literals using case statements, which do use pattern matching. When I said it was not possible, I was speaking of the syntax x => s.