In che modo i tipi esistenziali differiscono dalle interfacce?


11

Dato il tipo esistenziale

T = X.{op₁:X, op₂:Xboolean}

e questa interfaccia Java generica:

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 agli oggetti di Java (che include anche dettagli come thisparametri nascosti ecc.). Non mi interessano tanto queste cose quanto le differenze concettuali e semantiche, anche se se qualcuno volesse fare luce su alcuni punti più fini (come la differenza notazionale tra Tvs. T<X>), anche questo sarebbe apprezzato.


Risposte:


4

Hmm ... Quella definizione sembra molto simile a qualche esempio 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 Xsi applica il costruttore ∀ diventa effettivamente ∃. Si noti che quando si estrae valuenon si conosce il tipo e si dispone di un set di operazioni vuoto su di esso. Ma poiché viewValueè un po 'coerente con valueesso può essere applicato ad esso.

Immagino che la principale differenza di Java che interfacehai proposto sia il fatto che devi conoscere il tipo intermedio per passare il risultato di op₁a op₂. Cioè il sistema adeguato per il tipo esistenziale dovrebbe selezionare il tipo giusto che è garantito per esistere dalla condizione. Per esempio, si dovrebbe essere in grado di scrivere la funzione con il tipo: ∀X. X→(X→boolean)→T. Nel campione precedente tale funzione è Xutilizzata dal costruttore X 3 show( showè la funzione che accetta argomenti di qualsiasi tipo che implementa Showe restituisce String)

Aggiornato: ho appena riletto la tua domanda e penso di avere una costruzione adeguata 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 a menzionare this- in realtà è la tua opera.

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

PS Siamo spiacenti, non ho molta familiarità con Java, ma spero che tu abbia avuto l'idea.


Aggiungerò a questo che ti consigliamo di esaminare il tipo SAM (Single Abstract Method) che viene introdotto in Java 8 per il supporto della programmazione funzionale.
Martijn Verburg,

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 specifica per qualsiasi lingua. Gli scienziati informatici usano questo tipo di definizione per provare cose sul tipo e sulle lingue che lo implementano. L'interfaccia Java è una delle implementazioni Java del tipo formalmente definito.


no. cf william cook paper.
nicolas,

2

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

Un tipo esistenziale nasconde un tipo all'interno della sua implementazione da parte del consumatore. Intuitivamente, affinché X sia esistenziale in T, l'identità di X non può essere conosciuta da nessun consumatore; tutto ciò che dovrebbe essere noto è 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, tra cui il consumatore è libero di scegliere. L'interfaccia tipo T è esattamente questo. X è istanziato dal consumatore, che saprà esattamente quale tipo X è. Esiste un tipo T per ogni tipo X nell'universo.

Le esistenze non sono effettivamente presenti in Java come costrutti di linguaggio, tranne nel caso limitato di caratteri jolly ( List<?>). Ma sì, possono essere emulati con interfacce. Il problema diventa quindi più di progettazione.

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

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.