1

In Haskell, I wrote:

lt :: (Ord a) => a -> a -> Bool
lt x y 
 | x < y = True
 | otherwise = False

I tried the following unsuccessfully in Scala:

scala> def lt[A <: Ordered[A]](a: A, b: A): Boolean = a < b
lt: [A <: Ordered[A]](a: A, b: A)Boolean

Here's the REPL error:

scala> lt(10, 100)
<console>:9: error: inferred type arguments [Int] do not conform to method lt's type parameter bounds [A <: Ordered[A]]
              lt(10, 100)
              ^
<console>:9: error: type mismatch;
 found   : Int(10)
 required: A
              lt(10, 100)
                 ^
<console>:9: error: type mismatch;
 found   : Int(100)
 required: A
              lt(10, 100)
                     ^

How can I create a function lt in the above way for Scala?

Noah
  • 13,821
  • 4
  • 36
  • 45
Kevin Meredith
  • 41,036
  • 63
  • 209
  • 384
  • 2
    I think you need a *context bound* `[A : Ordered]` possibly with an `implicitly` call - see http://danielwestheide.com/blog/2013/02/06/the-neophytes-guide-to-scala-part-12-type-classes.html. Also, Ordering is the typecless, not Ordered - see http://like-a-boss.net/2012/07/30/ordering-and-ordered-in-scala.html – DNA Apr 08 '14 at 02:37

3 Answers3

3

Int doesn't inherit from Ordered, but the scala Predef provides an implicit Ordering which is what it uses to compare. This is the more idiomatic scala way (though I like the scalaz way more):

def lt[A](a: A, b: A)(implicit ordering:Ordering[A]): Boolean = ordering.lt(a, b)
Noah
  • 13,821
  • 4
  • 36
  • 45
0

I have had similar issues in trying to move from Haskell to Scala,

The short answer to your question would be this (using scalaz's Order instead of Ordering):

import scalaz._
import Scalaz._

def lt[A : Order](a: A, b: A): Boolean = {
    val u = implicitly[Order[A]]
    import u._
    a < b
}

And the reason your version of lt isnt working is that Int doesn't actually extend Ordered[A] and there is no implicit conversion happening in your version (but there is in the above version).

Understanding whats going here requires understanding of what Haskell does with its type classes and how Scala approximates it.

Upon compilation, Haskell effectively converts lt :: (Ord a) => a -> a -> Bool into a function lt :: Ord a -> a -> a -> Bool where Ord a is a dictionary of the functions defined in as Ord instance, and uses the < function defined there. There are no OO complications there, and (provided you dont break typeclass coherency with orphan instances) there should only be one choice for that dictionary for any given type.

What Scala does in the example above is implicitly transform the A object into whatever class that inherits Order[A] that happens to be in scope. I dont think i can explain it better than this person has explained it here: What are Scala context and view bounds?

Community
  • 1
  • 1
unfoldr
  • 141
  • 3
0

try "View Bound".

def lt[A <% Ordered[A]](a: A, b: A): Boolean = if (a < b) true else false

You can also try 'Context Bound'.

def lt[A : Ordering](a: A, b: A): Boolean = {
    val ord = implicitly[Ordering[A]]
    ord.lt(a, b)
}

In both cases, scala implicit mechanism does the trick.

smilingleo
  • 121
  • 4