How can I find the n! permutations of certain letters on Scala?
Scala 2.9 RC1:
scala> "abc".permutations.toList
res58: List[String] = List(abc, acb, bac, bca, cab, cba)
scala> def permutations[T](xs: List[T]): List[List[T]] = xs match {
| case Nil => List(Nil)
| case _ => for(x <- xs;ys <- permutations(xs diff List(x))) yield x::ys
| }
permutations: [T](xs: List[T])List[List[T]]
scala> permutations("abc".toList) foreach println
List(a, b, c)
List(a, c, b)
List(b, a, c)
List(b, c, a)
List(c, a, b)
List(c, b, a)
Related
In Scala 3, I'm able to write a poly-function of type 1:
val y = [C <: Int] => (x: C) => x * 2
When I try to generalise it into type 2:
val z = [C <: Int] => ([D <: Int] => (x: C, y: D) = x * y)
I got the following error:
DependentPoly.scala:19:37: Implementation restriction: polymorphic function literals must have a value parameter
So is this feature not implemented? Or I'm not writing it properly?
Implementation restriction: polymorphic function literals must have a value parameter means that
val y = [C <: Int] => foo[C]
is illegal (for example for def foo[C <: Int]: C => Int = _ * 2) while
val y = [C <: Int] => (x: C) => x * 2
is legal.
Similarly,
val z = [C <: Int] => [D <: Int] => (x: C, y: D) => x * y
val z = [C <: Int] => [D <: Int] => (x: C) => (y: D) => x * y
are illegal while
val z = [C <: Int, D <: Int] => (x: C, y: D) => x * y
val z = [C <: Int, D <: Int] => (x: C) => (y: D) => x * y
val z = [C <: Int] => (x: C) => [D <: Int] => (y: D) => x * y
val z = [C <: Int] => (_: C) => [D <: Int] => (x: C, y: D) => x * y
val z = [C <: Int] => (_: C) => [D <: Int] => (x: C) => (y: D) => x * y
are legal.
This is because of
trait PolyFunction:
def apply[A](x: A): B[A]
https://docs.scala-lang.org/scala3/reference/new-types/polymorphic-function-types.html
https://github.com/lampepfl/dotty/pull/4672
I'm essentially looking for the opposite of the type class Prepend[A, B].
If I have something like:
type A = String :: Int :: HNil
type B = Boolean :: Double :: HNil
val a: A = "a" :: 1 :: HNil
val b: B = false :: 2.1 :: HNil
scala> val ab = a ++ b
ab: shapeless.::[String,shapeless.::[Int,shapeless.::[Boolean,shapeless.::[Double,shapeless.HNil]]]] = a :: 1 :: false :: 2.1 :: HNil
I have an HList a of type A and an HList b of type B, I can find a prepend: Prepend[A, B] such that I can concatenate them with a ++ b.
But if I have an HList ab of type prepend.Out, how can I extract the original A and B? I can't seem to find a type class that does the job, and perhaps there isn't one. It seems like I would need something like trait Cut[A <: HList, B <: HList, c <: HList] that witnesses that C has been created by pre-pending A to B, though I'm not sure how I would go about generating witnesses.
Very roughly like:
def Cut[A <: HList, B <: HList, C <: HList](c: C)(implicit cut: Cut[A, B, C]): (A, B) = ???
You can do this fairly straightforwardly with Split:
import shapeless._, ops.hlist.{ Length, Prepend, Split }
class UndoPrependHelper[A <: HList, B <: HList, C <: HList, N <: Nat] {
def apply(c: C)(implicit split: Split.Aux[C, N, A, B]): (A, B) = split(c)
}
def undoPrepend[A <: HList, B <: HList](implicit
prepend: Prepend[A, B],
length: Length[A]
) = new UndoPrependHelper[A, B, prepend.Out, length.Out]
And then:
scala> type A = Int :: String :: Symbol :: HNil
defined type alias A
scala> type B = List[Int] :: Option[Double] :: HNil
defined type alias B
scala> type C = Int :: String :: Symbol :: List[Int] :: Option[Double] :: HNil
defined type alias C
scala> val a: A = 1 :: "foo" :: 'bar :: HNil
a: A = 1 :: foo :: 'bar :: HNil
scala> val b: B = List(1, 2, 3) :: Option(0.0) :: HNil
b: B = List(1, 2, 3) :: Some(0.0) :: HNil
scala> val c: C = a ++ b
c: C = 1 :: foo :: 'bar :: List(1, 2, 3) :: Some(0.0) :: HNil
scala> val (newA: A, newB: B) = undoPrepend[A, B].apply(c)
newA: A = 1 :: foo :: 'bar :: HNil
newB: B = List(1, 2, 3) :: Some(0.0) :: HNil
I recently added an "undo" operation for the Remove type class, and it might make sense to have something similar built into Prepend.
Prof. Odersky in Coursera course has implemented flatMap using for loops as following:
def flatMap[T, U](xs: List[T], f: T => Iterable[U]) = for (x <- xs; y <- f(x)) yield y
And here's some application on the two functions (result as expected):
val xs = List(1, 2, 3, 4, 5)
flatMap[Int, Int](xs, x=> List(x /2))
However, When I try implement the flatMap as:
for (x <- xs) yield f(x)
It does not return the correct answer, it returns a List of Lists (it should return one big list contains all elements of the inner lists)
My question is, What is the different that make flatMap works as expected; between both:
for (x <- xs; y <- f(x)) yield y
//And
for (x <- xs) yield f(x)
And Why for (x <- xs; y <- x * x) yield y not compiling?
Your second version doesn't involve a call to flatMap at all. You can use reify to de-sugar the for comprehension and see:
scala> import reflect.runtime.universe._
import reflect.runtime.universe._
scala> val f: Int => Iterable[Int] = null
f: Int => Iterable[Int] = null
scala> val xs = List(1, 2, 3, 4, 5)
xs: List[Int] = List(1, 2, 3, 4, 5)
scala> reify { for (x <- xs; y <- f(x)) yield y }
res0: reflect.runtime.universe.Expr[List[Int]] = Expr[List[Int]]($read.xs.flatMap(((x) => $read.f.apply(x).map(((y) => y))(Iterable.canBuildFrom)))(List.canBuildFrom))
scala> reify { for (x <- xs) yield f(x) }
res1: reflect.runtime.universe.Expr[List[Iterable[Int]]] = Expr[List[scala.Iterable[Int]]]($read.xs.map(((x) => $read.f.apply(x)))(List.canBuildFrom))
the first can be simplified to:
xs.flatMap(x => f(x).map(identity))
which is equivalent to:
xs.flatMap(f)
and the second can be simplified to:
xs.map(f)
Here is a function I wrote for concatenating elements of a List using an accumulator with tail recursion :
val l1 = List(1, 2, 3) //> l1 : List[Int] = List(1, 2, 3)
val l2 = List(1, 2, 3) //> l2 : List[Int] = List(1, 2, 3)
def func(l1: List[Int], l2: List[Int], acc: List[Int]): List[Int] = {
(l1, l2) match {
case (Nil, Nil) => acc.reverse
case (h1 :: t1, h2 :: t2) => {
func(t1, t2, h1 :: h2 :: acc)
}
}
} //> func: (l1: List[Int], l2: List[Int], acc: List[Int])List[Int]
func(l1, l2, List()) //> res0: List[Int] = List(1, 1, 2, 2, 3, 3)
This is my understanding of the call order
func( 1 :: 1 :: () )
func( 2 :: 2 :: 1 :: 1 : () )
func( 3 :: 3 :: 2 :: 2 :: 1 :: 1 : () )
So the call order is the reason why I must call reverse on base call of acc so that the List is ordered in same ordering initial List elements. To try to minimize the steps required to concatenate the lists I have tried to add the elements like this :
func(t1, t2, acc :: h1 :: h2)
instead of
func(t1, t2, h1 :: h2 :: acc)
but receive compile time error :
value :: is not a member of Int
So it seems I cannot prepend these elements to this List ?
When you write x :: y, y must be a list and x the element you want to prepend.
You can use acc :+ h1 :+ h2 to append h1 and h2 to acc, but note that adding elements to the end of the list is a relatively expensive operation (linear with the length of the list).
Why do both of the following foldLeft's result in the same output?
#1
scala> List(1,2,3).foldLeft(List[Int]())( (acc, el) => acc :+ el)
res114: List[Int] = List(1, 2, 3)
And, now using _ :+ _ as the (B, A) => B argument.
#2
scala> List(1,2,3).foldLeft(List[Int]())(_ :+ _)
res115: List[Int] = List(1, 2, 3)
In particular, the lack of explicitly appending to the accumulator in the second case confuses me.
_ :+ _ is simply a shorthand for (x1, x2) => x1 :+ x2, just as list.map(_.toString) is simply list.map(x => x.toString).
See more on the placeholder syntax here.