Int значение Prod в бесформенном - PullRequest
3 голосов
/ 12 февраля 2012

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

Выдержка из бесформенного nat.scala:

trait Prod[A <: Nat, B <: Nat] {
  type Out <: Nat
}

trait ProdAux[A <: Nat, B <: Nat, C <: Nat]

object Prod {
  implicit def prod[A <: Nat, B <: Nat, C <: Nat](implicit diff : ProdAux[A, B, C]) = new Prod[A, B] {
    type Out = C
  }
}

object ProdAux {
  import Nat._0

  implicit def prod1[B <: Nat] = new ProdAux[_0, B, _0] {}
  implicit def prod2[A <: Nat, B <: Nat, C <: Nat, D <: Nat]
    (implicit ev1 : ProdAux[A, B, C], ev2 : SumAux[B, C, D]) = new ProdAux[Succ[A], B, D] {}
}

До сих пор я придумал простое определение

def toInt[A <: Nat, B <: Nat, C <: Nat](p: Prod[A, B])
    (implicit paux: ProdAux[A, B, C], iv: ToInt[C]): Int = iv()

На самом деле этот подход потребует несколько избыточных реализаций эквивалентного кода, например суммы, разности, факториалы и т. д. Поэтому я бы предпочел использовать метод «по умолчанию» toInt[A <: Nat].

Как бы вы это сделали? И можно ли использовать внутренние типы (Prod#Out, Sum#Out, ...)?

1 Ответ

2 голосов
/ 26 февраля 2012

Извините, я пропустил этот вопрос ранее (кстати, бесформенный список рассылки - хорошее место, чтобы задать этот вопрос).

Я думаю, что вы немного неправильно поняли роль класса Prod: его экземпляры не являются самими Nat с, они являются свидетелями отношения, удерживающего три Nat с, а именно, что (A * B) == C. Таким образом, на самом деле не имеет особого смысла преобразовывать Prod экземпляров в Int с. Или, скорее, если бы это было так, то имело бы такой же смысл, чтобы результирующее значение соответствовало любому из A, B или C или тройке всех из них.

Для использования в качестве проверочных терминов в определениях методов показанный вами стиль в значительной степени соответствует назначению ... см. здесь для примера. Очевидно, что это не очень хорошо работает для игры с REPL. Чтобы сделать это немного более плавным, вы можете попробовать что-то вроде

def prod[A <: Nat, B <: Nat](implicit prod : Prod[A, B]) =
  new { def toInt(implicit ti : ToInt[prod.Out]) = ti() }

, который допускает взаимодействие REPL, например,

scala> prod[_2, _3].toInt
res0: Int = 6

Если это все еще не совсем то, что вам нужно, перейдите в список рассылки и набросайте, что вы хотели бы сделать.

...