在haskell中你可以:
Prelude> let double x = x + x // (1)
Prelude> let quadruple x = double (double x) //(2)
Prelude> :t double
double :: Num a => a -> a
Prelude> :t quadruple
quadruple :: Num a => a -> a
在 Scala 中,您必须明确指定 Num
scala> def double[T: Numeric] (a: T) = implicitly[Numeric[T]].plus(a, a)
double: [T](a: T)(implicit evidence$1: Numeric[T])T
scala> def quadruple[T: Numeric](a: T) = double(double(a))
quadruple: [T](a: T)(implicit evidence$1: Numeric[T])T
因为 haskell 的类型推断更聪明。 (1) 第一行确实找到了 typeclass Num:
Prelude> :info Num
class Num a where
(+) :: a -> a -> a //looks like structural types, but ...
(*) :: a -> a -> a
(-) :: a -> a -> a
negate :: a -> a
abs :: a -> a
signum :: a -> a
fromInteger :: Integer -> a
-- Defined in ‘GHC.Num’ //... but here is implementations found accross build - they are explicitly saying that they are instances of Num
instance Num Integer -- Defined in ‘GHC.Num’
instance Num Int -- Defined in ‘GHC.Num’
instance Num Float -- Defined in ‘GHC.Float’
instance Num Double -- Defined in ‘GHC.Float’
Scala 在结构类型方面也存在问题——你不能定义多态结构类型(不仅如此——你不能定义多态 lambdas)"Parameter type in structural refinement may not refer to an abstract type defined outside that refinement"
否则Num 将在 Scala 中定义为:
implicit class Num[T <: { def +(x:T):T }](a: T) = ... //will not work, and pretty slow by the way
查看其他答案以了解它的真正定义方式 (Numeric)。
在第 (2) 行编译器从 double 的应用程序推断 x (Num x) 的输入类型。 Scala 就是做不到这一点。它类似于haskell 的Num 将是:
scala> trait Num[T]{ val a: T; def + (b: Num[T]): Num[T] }
defined trait Num
scala> implicit class NumInt(val a: Int) extends Num[Int] {override def + (b: Num[Int]) = NumInt(a + b.a)}
defined class NumInt
scala> def double[T](a: Num[T]) = a + a
double: [T](a: Num[T])Num[T]
scala> double(5)
res4: Num[Int] = NumInt@424f5762
但问题还是一样 - 你必须在 scala 中指定输入类型 (a: Num[T]),它无法推断它们。
但是,即使在 Haskell 中,您也不能这样说:
Prelude> let double x = x +++ x
<interactive>:28:18:
Not in scope: ‘+++’
Perhaps you meant ‘++’ (imported from Prelude)
Otherwise `Num` would be defined in Scala as something like that:
而Haskell真正的鸭式打字也不是那么好用:http://chrisdone.com/posts/duck-typing-in-haskell