Если вы используете Scala (и, как я полагаю, на основе тега), одним из наиболее общих решений является написание кода вашей библиотеки для класса scala.math.Integral
:
def naturals[A](implicit f: Integral[A]) =
Stream.iterate(f.one)(f.plus(_, f.one))
Вы также можете использовать границы контекста и Integral.Implicits
для лучшего синтаксиса:
import scala.math.Integral.Implicits._
def squares[A: Integral] = naturals.map(n => n * n)
Теперь вы можете использовать эти методы с Int
или Long
или BigInt
по мере необходимости, поскольку экземпляры Integral
существуют для всех из них:
scala> squares[Int].take(10).toList
res0: List[Int] = List(1, 4, 9, 16, 25, 36, 49, 64, 81, 100)
scala> squares[Long].take(10).toList
res0: List[Long] = List(1, 4, 9, 16, 25, 36, 49, 64, 81, 100)
scala> squares[BigInt].take(10).toList
res1: List[BigInt] = List(1, 4, 9, 16, 25, 36, 49, 64, 81, 100)
Нет необходимости изменять код библиотеки: просто используйте Long
или BigInt
, где проблема переполнения, и Int
в противном случае.
Вы заплатите некоторый штраф с точки зрения производительности, но щедрость и способность отложить решение Int
-или- BigInt
могут стоить этого.