Learn You Scala for Great Good! Part 3

Learn You Scala for Great Good! Part 3

In my previous posts Learn You Scala for Great Good! and Learn You Scala for Great Good! Part 2 I told how I started studying Haskell in order to get knowledge in functional programming in Scala. While I was reading Learn You a Haskell for Great Good! I started to “translate” some examples from Haskell into Scala.
Today I shall take some interesting examples from the Recursion chapter of this book.

replicate function

The replicate function takes an Int and some element and returns a list that has several repetitions of the same element.

 

Haskell


    replicate :: (Num i, Ord i) => i -> a -> [a]  
    replicate n x  
        | n <= 0    = []  
        | otherwise = x:replicate (n-1) x

 

As I’ve already said there is no Ord typeclass in Scala. Let’s implement this function for integers:


    def replicate(i:Int, x: Int):List[Int] = {
      i match {
        case n if n <= 0 => Nil
        case n => x::replicate(n-1, x)
      }
    }
    println(replicate(7, 9))

 

But you don’t need to change much to implement it for general case. You can simply replace Int by Any.


    def replicate(i:, x: Any):List[Any] = {
      i match {
        case n if n <= 0 => Nil
        case n => x::replicate(n-1, x)
      }
    }

    println(replicate(12, 'a'))

 

But I prefer a generic function:


    def replicate[A](i:, x: A):List[A] = {
      i match {
        case n if n <= 0 => Nil
        case n => x::replicate(n-1, x)
      }
    }

    println(replicate(12, 'a'))

 

take function

The take function takes a certain number of elements from a list.

 

Haskell:


    take :: (Num i, Ord i) => i -> [a] -> [a]  
    take n _  
        | n <= 0   = []  
    take _ []     = []  
    take n (x:xs) = x : take (n-1) xs  

Scala :


    def take[A](n:Int, l:List[A]): List[A] = {
      (n, l) match {
        case (n, _) if n <= 0 => Nil
        case (_, Nil) => Nil
        case (n, x::xs) => x::take(n-1, xs)
      }
    }

    println(take(3, List(5, 34, 99, 8, 567, 222)))
    println(take(5, List("5", "34", "99", "8", "567", "222")))

I use pattern matching in Scala:

  • if we try to take a 0 or negative number of elements, we get an empty list
  • if the second parameter is an empty list , we get an empty list
  • the third pattern breaks the list into a head and a tail and the function is called again: x::take(n-1, xs)

 

reverse function

The reverse function simply reverses a list.

 

Haskell:


    reverse :: [a] -> [a]  
    reverse [] = []  
    reverse (x:xs) = reverse xs ++ [x]

Scala:


    def reverse[A](l: List[A]):List[A] = {
      l match {
        case Nil => Nil
        case x::xs => (reverse(xs) ::: x::Nil)
      }

    }

    println(reverse(1::2::3::4::4::5::6::7::Nil))

The edge condition is the empty list. If a list can be split to a head and a tail, the reversed list is equal to the reversed tail and then the head at the end.

Please follow and like us:

About Alexandre Kremlianski

Scala / Scala.js / JavaScript programmer

Leave a Reply

Your email address will not be published. Required fields are marked *