2016-11-20 13 views
3

Возможно ли реализовать доказательство равенства в Scala?Dependent Typing style Равноправие в Scala

В книге Type Driven Development с Idris приводится пример того, как можно определить тип доказательства равенства.

data (=): a -> b -> Type where 
    Refl : x = x 

Мой первый инстинкт, чтобы преобразовать это в Scala, это что-то вроде этого.

sealed trait EqualityProof[A, B] 
final case class EqualityProofToken[T](value: T) extends EqualityProof[value.type, value.type] 

Однако это требует, чтобы я доказал компилятору, что два объекта, которые я хочу сравнить, - это один и тот же точный экземпляр. В идеале это будет работать для равных объектов, которые являются разными экземплярами, хотя это может быть слишком много. Это просто ограничение, которого нельзя избежать из-за того, что Scala допускает изменчивые данные? Есть ли способ реализовать это правильно? Если нет, это обходное решение, отличное от использования asInstanceOf, чтобы лежать в компиляторе (или как ограничить использование asInstanceOf)?

Обновление: похоже, существует некоторая путаница в определении проблемы, поэтому я добавляю более полный пример Идриса.

data EqNat : (num1 : Nat) -> (num2 : Nat) -> Type where 
Same : (num : Nat) -> EqNat num num 

sameS : (k : Nat) -> (j : Nat) -> (eq : EqNat k j) -> EqNat (S k) (S j) 
sameS k k (Same k) = Same (S k) 

checkEqNat : (num1 : Nat) -> (num2 : Nat) -> Maybe (EqNat num1 num2) 
checkEqNat Z Z = Just (Same 0) 
checkEqNat Z (S k) = Nothing 
checkEqNat (S k) Z = Nothing 
checkEqNat (S k) (S j) = case checkEqNat k j of 
           Nothing => Nothing 
           Just eq => Just (sameS _ _ eq) 

В этот момент экземпляр EqNat может быть использован для выполнения операций, которые требуют одинаковых значений, таких как сжать в списки длин, которые оказались равными.

+0

Интересно, могут ли теги классов или теги типа сделать эту работу ... Интересный вопрос в любом случае! – Alec

+1

Scala * does * имеют зависимую типизацию в виде зависимых типов методов и зависимых от пути типов. Однако кодировка не 1: 1, вы не можете просто сопоставить типы зависимостей типа Idris/Agda/Coq/HOL/Guru/Epigram с Scala, вы должны их кодировать. Я далек от достаточно знаний, чтобы рассказать вам, как это сделать. Из моего ограниченного понимания «зависимая» часть кодируется с использованием зависимых от пути типов и зависимых типов методов, а часть «доказательство» (или «поиск») кодируется с использованием неявного разрешения (которое обеспечивает необходимое обратное отслеживание). –

+0

Мне не совсем понятно: доказывает ли вещь Идриса, что одноэлементные типы двух значений будут равны, так что у вас есть доказательство времени компиляции, равное двум значениям? Или это просто доказывает, что любые два типа равны, например, в scala 'def equal [A, B] (a: A, b: B) (неявный ev: A =: = B)'? –

ответ

0

Простой перевод с Идрисом довольно проста, вы просто использовать неявный, чтобы обеспечить время компиляции доказательства:

sealed trait Equality[A, B] 

case class Refl[A]() extends Equality[A, A] 

case object Equality { 

    implicit def refl[B]: Equality[B, B] = Refl[B]() 
} 

Он размещен в объекте компаньона, так что всегда будет в объеме, когда вы» требуя неявного типа Equality.

Вы можете найти более активное определение такого типа равенства в библиотеке ohnosequences/cosas вместе с некоторыми tests/examples. (отказ от ответственности: я один из сопровождающих)

+2

Насколько я вижу, это доказывает равенство типа, а не равенство равенства. – MI3Guy

+0

Что вы подразумеваете под «доказательством» равенства ценности. Вопрос касался равенства типов, и это пример вашего примера Идриса. Вы можете _compare_ значения, но в _runtime_. – laughedelic

+0

Пример Идриса вполне способен доказать равенство значений. Похоже, в Scala нет никакого способа сделать это. – MI3Guy