Как объявить в Scala сигнатуры типов, необходимые для реализации множества арифметических систем, которые имеют общий признак, объявляющий операции? Я думал, что решил, что решил, пока не попытаюсь добавить некоторые вспомогательные реализации в базовый признак/класс. В следующем фрагменте кода (который компилирует) заметьте, что sq() определяется как это * self, тем более очевидным это * это. И self() не может быть реализован в признаке (мы должны подождать, пока мы не достигнем конкретного расширяющегося класса для его реализации).Как объявить параметризованную арифметику типа в Scala?
trait NumberBase [NUMBERTYPE <: NumberBase[NUMBERTYPE]] {
// type NUMBERTYPE >: this.type
def *(that: NUMBERTYPE):NUMBERTYPE
def self:NUMBERTYPE
def sq:NUMBERTYPE = { this*self }
}
class D(val v:Double) extends NumberBase[D] {
def self:D = { this }
def *(that: D):D = { new D(this.v*that.v) }
}
Вопрос/цель состоит в том: удалить использование самости() или (по крайней мере, двигаться самостоятельно() 'ы реализации в NumberBase) без изменения типа подписи * в D. Множество исправлений в вышеупомянутая ссылка делает производный класс неосуществимым (такие вещи, как новый D(), не являются типом, возвращаемым символом * или *, имеющим недопустимую сигнатуру типа в D). Я не возражаю против того, что подписи становятся более уродливыми, но я хотел бы, чтобы код выражал то, что этот код выражает: что производные классы работают только по своим собственным типам и возвращают экземпляры своего типа (они не перемещаются вверх и вниз в иерархии).
Я нашел здесь некоторое обсуждение, в котором перечислены некоторые проблемы (но не вижу решения): http://www.scala-lang.org/node/839. Некоторые проблемы, с которыми вы не сталкиваетесь, пока не увидите как базовый класс, так и реализацию.
Полный код с приведенным выше описанием работы (принудительное внедрение классов для реализации self()) приводится здесь: https://github.com/WinVector/AutoDiff, где мы используем тот факт, что разные арифметические системы используют один и тот же базовый класс или свойство для записи общих функций над различными арифметическими реализациями. Это позволяет использовать упаковку стандартной машинной арифметики (например, D) или что-то еще (например, систему чисел, которая вычисляет градиенты как побочный эффект).
Это также актуально: https://tpolecat.github.io/2015/04/29/f-bounds.html – Daenyth