Lungo le linee di this question, sto cercando di trovare un modo per ottenere il compilatore Scala di dedurre il massimo sottotipo comune di due tipi A e B.Trova più grande sottotipo comune di due tipi Scala
Qualcosa come "A senza B", in cui la definizione è:
(A without B = C) === (A = C with B)
o una funzione che restituisce tipo C, dove:
EDIT:
A <: C && C <:!< B
ie. A è un sottotipo di C e C non è un sottotipo di B
In effetti, mi aspetto che qualcuno indichi che questo non è lo stesso del "più grande sottotipo comune", dal momento che in realtà non è necessario che sia A <: B
.
Usage:
trait Syntax
trait ANYSYNTAX extends Syntax
trait NUMERIC extends ANYSYNTAX
trait DISCRETE extends ANYSYNTAX
trait POSITIVE extends ANYSYNTAX
trait CONST extends ANYSYNTAX
type NUMCONST = NUMERIC with CONST
type POSCONST = POSITIVE with CONST
type ORDINALCONST = DISCRETE with CONST
type INTEGER = NUMERIC with DISCRETE
type POSNUM = POSITIVE with NUMERIC
type POSINT = POSNUM with INTEGER
type INTCONST = INTEGER with NUMCONST with ORDINALCONST
type POSNUMCONST = POSNUM with POSCONST with NUMCONST
type POSINTCONST = POSNUMCONST with INTCONST with POSINT
Poi vorrei essere in grado di propagare vincoli di tipo, come segue:
abstract class Expression[+R](val args: Expression[_]*)
case class Add[A <: R, R <: NUMERIC](arg1: Expression[A], arg2: Expression[A]) extends Expression[R] {
case class Subtract[A <: R, R : A without POSITIVE](arg1: Expression[A], arg2: Expression[A]) extends Expression[R] {
case class Multiply[A <: R, R <: NUMERIC](arg1: Expression[A], arg2: Expression[A]) extends Expression[R]{
case class Divide[A <: R, R : A without DISCRETE](arg1: Expression[A], arg2: Expression[A]) extends Expression[R] {
Ho cercato di trovare qualcosa usando alcuni vincoli di tipo presi in prestito da altre risposte SO:
sealed class =!=[A,B]
trait LowerPriorityImplicits {
implicit def equal[A]: =!=[A, A] = sys.error("should not be called")
}
object =!= extends LowerPriorityImplicits {
implicit def nequal[A,B](implicit same: A =:= B = null): =!=[A,B] =
if (same != null) sys.error("should not be called explicitly with same type")
else new =!=[A,B]
}
// Encoding for "A is not a subtype of B"
trait <:!<[A, B]
// Uses ambiguity to rule out the cases we're trying to exclude
implicit def nsub[A, B] : A <:!< B = null
implicit def nsubAmbig1[A, B >: A] : A <:!< B = null
implicit def nsubAmbig2[A, B >: A] : A <:!< B = null
ho alcuni casi di test:
implicitly[POSINT <:!< CONST]
implicitly[POSITIVE <:!< OPINION]
implicitly[DOGMA <:!< CONST]
implicitly[POSINTCONST <:< POSITIVE with CONST]
implicitly[POSINTCONST <:< POSCONST]
implicitly[POSITIVE with CONST <:!< POSINTCONST]
implicitly[POSITIVE =:= POSCONST without CONST]
implicitly[NUMERIC =:= INTEGER without DISCRETE]
implicitly[POSINT =:= POSINTCONST without CONST]
Questi dovrebbero fallire:
implicitly[POSINT =:= POSINTCONST without OPINION]
implicitly[POSINT with OPINION =!= POSINTCONST without OPINION]
Non sono sicuro di aver capito la tua definizione. Sembra che se A <: B', quindi 'C' non esiste, e altrimenti' C' è solo 'A'. –
@TravisBrown Ad esempio, 'C: POSINT',' B: CONST'. Quindi 'A: C con B' = POSINTCONST. Secondo la mia prima definizione quindi, 'POSINTCONST senza CONST =: = POSINT'. Se d'altra parte 'A <:! RealName
In realtà @Travis ho fatto un errore nella mia seconda definizione (ora fisso, spero). – RealName