In haskell you can:
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
In scala you have to specify Num
explicitly
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
Because haskell's type inferrence is smarter. (1)st line did find 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’
Also Scala has problems with structural types - you can't define polymorphic structural type (not only this - you ca not define polymorphic lambdas) "Parameter type in structural refinement may not refer to an abstract type defined outside that refinement"
Otherwise Num
would be defined in Scala as something like that:
implicit class Num[T <: { def +(x:T):T }](a: T) = ... //will not work, and pretty slow by the way
See other answers to find out how it's really defined (Numeric
).
In the (2)nd line compiler inferred input type for x
(Num x
) from double
's application. Scala just can't do that. Its analog to the haskell's Num
would be:
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
But the problem is still same - you have to specify input types (a: Num[T]
) in scala, it cannot infer them.
However, even in Haskell you can't let's say:
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:
And Haskell's real duck typing is not so easy to use: http://chrisdone.com/posts/duck-typing-in-haskell