在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
?
答案 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 a
是a
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隐式机制都可以解决问题。