Scala exercise

A result of a discussion in the #scala IRC channel.

Write a minimum function that works on Array[String] and List[Int]. (see error("todo"))

trait Foldable[-F[_]] {
  def foldl[A, B](f: (A, B) => A, a: A, as: F[B]): A
 
  def reducel[A](f: (A, A) => A, as: F[A]): Option[A] = foldl[Option[A], A]((a1, a2) => 
    Some(a1 match {
      case None => a2
      case Some(x) => f(a2, x)
    }), None, as)
}
 
object Foldable {
  val ListFoldable = new Foldable[List] {
    def foldl[A, B](f: (A, B) => A, a: A, as: List[B]) =
      as.foldLeft(a)(f)
  }
 
  val ArrayFoldable = new Foldable[Array] {
    def foldl[A, B](f: (A, B) => A, a: A, as: Array[B]) =
      as.foldLeft(a)(f)
  }
}
 
sealed trait Ordering
case object LT extends Ordering
case object EQ extends Ordering
case object GT extends Ordering
 
// contra
trait Order[A] {
  def compare(a1: A, a2: A): Ordering
 
  def min(a1: A, a2: A) =
    if(compare(a1, a2) == LT) a1 else a2
}
 
object Order {
  def order[A](f: (A, A) => Ordering): Order[A] = new Order[A] {
    def compare(a1: A, a2: A) = f(a1, a2)
  }
 
  val IntOrder = order[Int]((a1, a2) => 
    if(a1 > a2) GT
    else if(a1 < a2) LT
    else EQ)
 
  val StringOrder = order[String]((a1, a2) =>
    if(a1 > a2) GT
    else if(a1 < a2) LT
    else EQ)
}
 
object Main {
  import Foldable._
  import Order._
 
  def minimum[F[_], A](as: F[A], order: Order[A], fold: Foldable[F]) =
    // Zm9sZC5yZWR1Y2VsW0FdKChhLCBiKSA9PiBvcmRlci5taW4oYSwgYiksIGFzKQ==
    error("todo")
 
  def main(args: Array[String]) {
    val i = minimum(args, StringOrder, ArrayFoldable)
    println(i)
 
    val j = minimum(List(5, 8, 2, 9), IntOrder, ListFoldable)
    println(j)    
  }
}

4 Responses to “Scala exercise”

  1. Steven Shaw Says:

    Thanks for making this an easy one :)

  2. Arnaud Bailly Says:

    Thanks for the exercises. I tried to solve this one but got a compilation error:

    scalac -Xprint:typer -explaintypes exercise.scala; scala tony.Main
    exercise.scala:62: error: inferred the kinds of the type arguments (Array[String],String) do not conform to the expected kinds of the type parameters (type F,type A).
    Array[String]'s type parameters do not match type F's expected parameters: class Array has one type parameter, but type F has one
        val i = minimum(args, StringOrder, ArrayFoldable)
                ^
    exercise.scala:62: error: type mismatch;
     found   : java.lang.Object with tony.Foldable[Array]
     required: tony.Foldable[Array[String]]
        val i = minimum(args, StringOrder, ArrayFoldable)
                                           ^
    java.lang.Object with tony.Foldable[Array] < tony.Foldable[Array[String]]?
      java.lang.Object < tony.Foldable[Array[String]]?
         < tony.Foldable[Array[String]]?
        false
      false
      tony.Foldable[Array] < tony.Foldable[Array[String]]?
        Array[String] < Array?
        false
      false
    false
    

    What am I doing wrong ? Note that I am using scala 2.7.7 on Linux.

    Best regards,
    Arnaud

  3. Tony Morris Says:

    Hi Arnaud,
    I compiled against Scala 2.8.0 which will make quite a difference.

  4. oxbow Says:

    Well, that was easier than I was expecting

Leave a Reply