带有'Ordered *'类型的Scala中的小于

时间:2014-04-08 02:11:26

标签: scala haskell

在Haskell,我写道:

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

我在Scala中尝试了以下失败的成功:

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

这里是REPL错误:

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)
                     ^

如何以上述方式为Scala创建函数lt

3 个答案:

答案 0 :(得分:3)

Int不会继承Ordered,但scala Predef会提供隐式Ordering,这是它用来比较的内容。这是更惯用的scala方式(虽然我更喜欢scalaz方式):

def lt[A](a: A, b: A)(implicit ordering:Ordering[A]): Boolean = ordering.lt(a, b)

答案 1 :(得分:0)

我在尝试从Haskell迁移到Scala时遇到过类似的问题,

对您的问题的简短回答是这样的(使用scalaz&#39; Order代替Ordering):

import scalaz._
import Scalaz._

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

您的lt版本无效的原因是Int实际上并未扩展Ordered[A],并且您的版本中没有发生隐式转换(但是上面的版本)。

了解这里的内容需要了解Haskell对其类型类的作用以及Scala如何对其进行近似。

编译后,Haskell有效地将lt :: (Ord a) => a -> a -> Bool转换为函数lt :: Ord a -> a -> a -> Bool,其中Ord aa Ord实例中定义的函数的字典,并且使用那里定义的<函数。那里没有OO并发症,并且(如果你不打破与孤儿实例的类型类一致性),对于任何给定类型,该字典应该只有一个选择。

Scala在上面的示例中所做的是将A对象隐式转换为任何继承Order[A]的类,这些类恰好在范围内。我不认为我可以解释它比这个人在这里解释的更好:What are Scala context and view bounds?

答案 2 :(得分:0)

尝试“View Bound”。

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

你也可以试试'Context Bound'。

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

在这两种情况下,scala隐式机制都可以解决问题。