List.sum on custom class

后端 未结 3 531
日久生厌
日久生厌 2021-01-15 03:32

I have the following code that represents GF2 field:

trait GF2 {
  def unary_- = this
  def + (that: GF2): GF2
  def * (that: GF2): GF2

  def / (that: GF2)          


        
相关标签:
3条回答
  • 2021-01-15 04:12

    You need a Numeric[GF2] implicit:

    trait GF2IsNumeric extends Numeric[GF2] {
      def plus(x: GF2, y: GF2): GF2 = x + y
      def minus(x: GF2, y: GF2): GF2 = x + (-y)
      def times(x: GF2, y: GF2): GF2 = x * y
      def negate(x: GF2): GF2 = -x
      def fromInt(x: Int): GF2 = ???
      def toInt(x: GF2): Int = ???
      def toLong(x: GF2): Long = ???
      def toFloat(x: GF2): Float = ???
      def toDouble(x: GF2): Double = ???
      override def zero = Zero
      override def one = One
    }
    
    trait GF2Ordering extends scala.math.Ordering[GF2] {
      override def compare(a: GF2, b: GF2) = if (a == b) 0 else if (b == One) 1 else -1
    }
    
    implicit object GF2IsNumeric extends GF2IsNumeric with GF2Ordering
    

    Then you can do:

    println(List(One, One, Zero, One).sum)
    // One
    
    0 讨论(0)
  • 2021-01-15 04:18

    You need to implement a version of Numeric for your trait in order for it to work. See here for the full definition you'll need to create.

     object InScope{
       implicit object GF2Numeric extends Numeric[GF2]{
         //..your implementation here
       }
     }
    

    The full signature of sum on a List is actually:

     def sum(implicit num: Numeric[A])
    

    Where by the A is the type of the List[A].

    0 讨论(0)
  • 2021-01-15 04:28

    Look at the signature of sum:

    def sum[B >: A](implicit num: Numeric[B]): B
    

    I was about to suggest that you make GF2 a member of Numeric typeclass by providing and implicit value of type Numeric[GF2], but then I looked at the definition of Numeric and realized that it contains a ton of operations completely irrelevant to summation that you would have to implement.

    I don't like this, I think sum method should require some more abstract typeclass (a monoid, perhaps?).

    So, I think your best option (unless you want to implement entire Numeric instance) is to use either reduce (will work only with non-empty lists) or fold:

    yourList.reduce(_ + _)
    yourList.fold(Zero)(_ + _)
    
    0 讨论(0)
提交回复
热议问题