In che modo i tipi esistenziali differiscono dalle interfacce?

10

Dato il tipo esistenziale

T = ∃X.{op₁:X, op₂:X→boolean}

e questa generica interfaccia Java:

interface T<X> {
    X op₁();
    boolean op₂(X something);
}

Quali sono le differenze fondamentali tra il tipo esistenziale e l'interfaccia Java?

Ovviamente ci sono differenze sintattiche e l'orientamento all'oggetto di Java (che include anche dettagli come parametri this nascosti ecc.). Non mi interesso tanto di queste come delle differenze concettuali e semantiche - sebbene se qualcuno volesse fare chiarezza su alcuni punti più fini (come la differenza di notazione tra T vs. T<X> ), sarebbe apprezzato anche questo .

    
posta stakx 02.01.2012 - 04:22
fonte

3 risposte

4

Hmm ... Quella definizione sembra molto simile ad un campione di haskell che ho visto molto tempo fa.

{-# LANGUAGE ExistentialQuantification #-}
data X = forall a . X { value :: a, viewValue :: a -> String }
instance Show X where show (X { value = x, viewValue = f}) = f x
sample :: [X]
sample = [X 3 show, X "abc" show, X 3.14 show]

Quando viene applicato il costruttore X ∀ diventa effettivamente ∃. Si noti che quando si estrae value non si conosce il tipo e si ha un set vuoto di operazioni su di esso. Ma poiché viewValue è un po 'coerente con value può essere applicato ad esso.

Immagino che la principale differenza di %% di Java proposta sia il fatto che devi conoscere il tipo intermedio per passare il risultato di interface a op₁ . Cioè sistema corretto per tipo esistenziale dovrebbe selezionare il tipo giusto che è garantito per condizione. Cioè dovresti essere in grado di scrivere la funzione con tipo: op₂ . Nel campione precedente tale funzione è ∀X. X→(X→boolean)→T costruttore utilizzato in X ( X 3 show è una funzione che prende l'argomento di qualsiasi tipo che implementa show e restituisce Show )

Aggiornato: ho appena riletto la tua domanda e penso di avere una corretta costruzione per Java:

interface T {
    boolean op₂();
}
...
T x = new T() {
    private final int op₁ = ...;
    public boolean op₂() { return ((op₁ % 2) == 0); }
};
T y = new T() {
    private final char op₁ = ...;
    public boolean op₂() { return ('0' <= op₁ && op₁ <= '9'); }
};
if (x.op₂() && y.op₂()) ...

Hai ragione nel menzionare String - in realtà è il tuo caso.

Quindi immagino di aver capito ora che i linguaggi OOP classici (Java, C #, C ++ ecc.) implementano sempre il tipo esistenziale con valore singolo this e una funzione su di esso chiamata "metodi" che implicitamente chiamata con quel valore:)

P.S. Scusa, non ho molta familiarità con Java, ma spero che tu abbia avuto l'idea.

    
risposta data 02.01.2012 - 10:12
fonte
2

L'unica differenza è che l'interfaccia Java in realtà significa qualcosa per il compilatore Java.

Il tipo esistenziale è la definizione formale di un tipo, non specifico per qualsiasi lingua. Gli informatici usano questo tipo di definizione per provare le cose sul tipo e sulle lingue che lo implementano. L'interfaccia Java è una delle implementazioni di Java del tipo definito formalmente.

    
risposta data 02.01.2012 - 18:22
fonte
2

I 2 tipi presentati sono molto diversi tra loro. La definizione dell'interfaccia che hai scritto è di tipo universale (i generici di Java in generale rientrano in questa categoria).

Un tipo esistenziale nasconde un tipo nella sua implementazione dal consumatore. Intuitivamente, poiché X è esistenziale in T, l'identità di X non può essere conosciuta da nessun consumatore; tutto ciò che dovrebbe essere conosciuto è l'insieme delle operazioni fornite alla definizione. Esiste un tipo T per un certo tipo X.

Al contrario, un tipo universale definisce le operazioni applicabili a tutti i tipi, da cui il consumatore è libero di scegliere. L'interfaccia di tipo T è esattamente quella. X viene istanziato dal consumatore, che saprà esattamente quale tipo X è. Esiste un tipo T per ogni tipo X nell'universo.

Gli esistenziali non sono effettivamente presenti in Java come costrutto linguistico, tranne nel caso limitato di caratteri jolly ( List<?> ). Ma sì, possono essere emulati con interfacce. Il problema diventa quindi più di design.

Come ho già sottolineato, in un'impostazione orientata agli oggetti, gli elementi esistenziali diventano difficili da implementare perché il modo in cui di solito codi informazioni sul tipo di X (cosa puoi fare con esso) è di avere funzioni membro in un tipo di interfaccia che X implementa. In breve, le interfacce possono acquistare alcune funzionalità di astrazione di tipo, ma richiedono l'eliminazione dell'esistenziale in una certa misura.

    
risposta data 06.01.2012 - 10:59
fonte

Leggi altre domande sui tag