Search code examples
arraysscalagenericsfoldleft

Scala: How do I use foldLeft with a generic array?


I've this method:

def isSorted[A](as: Array[A], ordered: (A, A) => Boolean): Boolean = {
    val sorted = for (it <- as.sliding(2))
      yield {
        if (it.length == 2) ordered.apply(it(0), it(1))
        else true
      }

    sorted.find(!_).isEmpty
}

What I'd like to do is use foldLeftand apply the binary operator. However, foldLeft requires an initial value and I don't know what initial value I can provide without knowing the real type of A.


Solution

  • I think what you're doing can be simplified.

    def isSorted[A](as: Array[A], ordered: (A, A) => Boolean): Boolean = {
      if (as.size < 2)
        true
      else
        as.sliding(2).find(x => !ordered(x(0),x(1))).isEmpty
    }
    
    isSorted: [A](as: Array[A], ordered: (A, A) => Boolean)Boolean
    
    scala> isSorted( Array(2), {(a:Int,b:Int) => a < b} )
    res42: Boolean = true
    
    scala> isSorted( Array(2,4), {(a:Int,b:Int) => a < b} )
    res43: Boolean = true
    
    scala> isSorted( Array(2,4,5), {(a:Int,b:Int) => a < b} )
    res44: Boolean = true
    
    scala> isSorted( Array(2,14,5), {(a:Int,b:Int) => a < b} )
    res45: Boolean = false
    

    Or, perhaps a little more concisely (but not necessarily easier to understand):

    def isSorted[A](as: Array[A], ordered: (A, A) => Boolean): Boolean = {
      if (as.size < 2)
        true
      else
        !as.sliding(2).exists(x => ordered(x(1),x(0)))
    }
    

    UPDATE

    OK, I think I've got the concise prize nailed.

    def isSorted[A](as: Array[A], ordered: (A, A) => Boolean): Boolean =
      as.isEmpty || as.init.corresponds(as.tail)(ordered)