Тип параметризованной арифметики? - PullRequest
2 голосов
/ 07 июля 2011

Попытка придумать, как вычесть 5 минут из 2 часов.

Нет смысла вычитать 5 из 2, потому что в итоге мы получаем -3 общих единицы времени, что бесполезно.Но если «час» является подтипом «минуты», мы можем преобразовать 2 часа в 120 минут и получить 115 минут, или 1 час и 55 минут.

Аналогично, если мы хотим добавить 5 яблок к5 апельсинов, мы не можем оценить это с точки зрения яблок, но можем ожидать, что в итоге получим 10 фруктов.

Кажется, в приведенных выше примерах, и, как правило, при использовании числа в качестве прилагательного, целые числа должны бытьпараметризованный типом объекта, который они описывают.Я думаю, что было бы очень полезно, если бы вместо объявления

val hours = 2
val minutes = 5

вы могли бы сделать что-то вроде

val hours = 2[Hour]
val minutes = 5[Minute]
val result = hours - minutes
assert (result == 115[Minute])

Есть ли что-то подобное, будет ли это полезно, и это то, чтоможет быть реализовано?

РЕДАКТИРОВАТЬ : чтобы уточнить, приведенный выше пример времени - просто случайный пример, который я придумал.Мой вопрос заключается в том, является ли вообще идея параметризованных чисел полезной концепцией, так же как вы параметризовали списки и т. Д. (Ответ может быть «нет», я не знаю!)

Ответы [ 4 ]

6 голосов
/ 07 июля 2011

Вы можете сделать это, имея два класса для Часов и Минут, наряду с неявной функцией преобразования из часов в минуты

trait TimeUnit
case class Hour(val num: Int) extends TimeUnit      
case class Minute(val num: Int) extends TimeUnit {
  def - (sub: Minute) = Minute(num - sub.num)
}

implicit def hour2Minute(hour: Hour) = Minute(hour.num * 60)

Это позволяет вам сделать что-то вроде

val h = Hour(2) - Minute(30) //returns Minute(90)
3 голосов
/ 07 июля 2011

Вы можете найти некоторые примеры для этого в структуре лифта ( spec ).

import net.liftweb.utils.TimeHelpers._
3.minutes == 6 * 30.seconds

(Примечание: кажется, вам нужны разумные числа для правильного сравнения. Например.Может быть не более 60 секунд.)

2 голосов
/ 08 июля 2011

Вы можете попробовать scala-time , который является оберткой вокруг Joda Time и делает его немного более идиоматичным для Scala, включая некоторые DSL для вычислений периода времени, аналогичночто Брайан Агнью предложил в своем ответе.

Например,

2.hours + 45.minutes + 10.seconds

создает Joda Period.

1 голос
/ 07 июля 2011

Мне кажется, здесь пригодится DSL.Таким образом, вы можете написать

2.hours - 5.minutes

, и соответствующие преобразования будут выполнены для преобразования 2 часов в объект Hours (значение 2) и т. Д.

Существует множество ресурсов, описывающих возможности DSL в Scala.например, см. это от O'Reilly

...