In Scala, why can't I implement a trivial generic function like this?

前端 未结 3 1399
太阳男子
太阳男子 2021-01-20 03:30

I want a generic function called \"double\", which behaves like this and could be applied to any type with def +(x:T):T method:

double(\"A\")
&g         


        
3条回答
  •  长情又很酷
    2021-01-20 04:12

    This is a perfect example of when to use typeclasses.

    + is just a function. You've given the compiler no information such as

    def +(t : T, t : T) : T = ...
    

    And you couldn't, because you don't have any idea what a T is.

    Here it would work as follows. You have a type constructor, called Doubles:

    trait Doubles[T]{
      def double(t : T) : T
    }
    

    Now in a companion object, just for convenience, I'm going to rewrite your double function as follows:

    object Doubles{
      def double[T](t : T)(implicit doubles : Doubles[T]) =    doubles.double(t)
    }
    

    So this says, I can double a T, as long as there's a Doubles for T in scope, or you explicitly provide me with a Doubles for T. Otherwise, I won't be able to double a T, and you'll get a compiler error.

    The following are going to be instances of that typeclass Doubles[T]:

    object Implicits{
        //Now, you wouldn't want to have to write this for 
        //every kind of number.  Scala already provides you with a numeric
        //typeclass.  So here's a function that gives a Doubles[N] 
        //whenever you ask for a Doubles[Numeric[T]], i.e. a Doubles for a     
        //member of the Numeric typeclass:
    
        implicit def numDoubler[N](implicit num : Numeric[N]) : Doubles[N] = new Doubles[N]{
            def double(n : N) : N = num.plus(n,n)
        }
    
        implicit object stringDoubler extends Doubles[String]{
            def double(t : String) : String = t + t
        }
    
     //So something like this is no longer needed:
     // implicit object intDoubler extends Doubles[Int]{
     //   def double(t : Int) : Int = t + t
     // }
    
    }
    

提交回复
热议问题