mayton2019
@mayton2019
Bigdata Engineer

Как в Scala обобщить Int и BigInt?

Пример из книжки Степанова. Египетское умножение. Я реализовал для целых чисел (Int)

def half(a:Int) : Int = a / 2
def half(a:BigInt) : BigInt = a / 2

def odd(a:Int) : Boolean = a % 2 == 1
def odd(a:BigInt) : Boolean = a % 2 == 1

def mult_acc4(n:Int, a:Int, r:Int = 0) : Int = (odd(n), n) match {
  case (true, 1) => r + a
  case (true, _) => mult_acc4(half(n), a + a, r + a)
  case (_,_)     => mult_acc4(half(n), a + a, r)
}

Потом был интерес сделать в BigInt чтобы Египетское умножение себя хоть как-то показало на длинных числах.
def mult_acc5(n:BigInt, a:BigInt, r:BigInt = 0) : BigInt = (odd(n), n) match {
  case (true, 1) => r + a
  case (true, _) => mult_acc5(half(n), a + a, r + a)
  case (_,_)     => mult_acc5(half(n), a + a, r)
}

Здесь пришлось сделать еще две реализации для проверки нечетных odd() и для деления на 2 half().
После этого я стал искать обобщенную реализацию. Сделал интерфейс числа которое складывает и делит и прочее.
И получается что писанины у меня стало от этого только больше. И баги ООП - как тушение пожара. Фиксишь один - лезет
следующих два.

trait PolyNum[T] {
  def +(x:T) : T
  def half : T
  def odd : Boolean
  def one : T
}


// illegal trait inheritance: superclass AnyVal does not derive from trait PolyNum's superclass Object
case class X(v:BigInt) extends AnyVal with PolyNum[BigInt] {
  override def +(x:BigInt) : BigInt = v + x
  override def odd : Boolean = v % 2 == 1
  override def half : BigInt = v / 2
  override def one : BigInt = BigInt(1)
}

// TODO: Fix
def mult_acc6[T](n:PolyNum[T], a:PolyNum[T], r:PolyNum[T]) : PolyNum[T] = (n.odd, n) match {
  case (true, n.one) => r + a
  case (true, _) => mult_acc6(n.half, a + a, r + a)
  case (_,_)     => mult_acc6(n.half, a + a, r)
}

Чувсвтую что ошибаюсь. Вот где?
Как красиво и изящно обобщить операции над целым и над BigInt?
  • Вопрос задан
  • 244 просмотра
Пригласить эксперта
Ответы на вопрос 1
sheerluck
@sheerluck
А чем просто генерики не подходят?
def mult_acc11[T](n:T, a:T, r:T = 0) : Int = ...
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы