I sottotipi di funzioni di livello inferiore-aritmetico sono quelli di livello più alto?

7

Ho scoperto che non esiste un concetto simile a "sottotipizzazione basata sull'arità" in molte lingue in cui ho programmato, in cui le funzioni di ordine superiore potrebbero consumare funzioni di arità inferiore rispetto al loro tipo di argomento, differendo in un modo coerente: ad esempio, mantenendo gli argomenti più a sinistra in ordine o richiedendo coppie di tipo nome corrispondenti. Ad esempio, (A) -> C <: (A, B) -> C tale che ((A, B) -> C) -> D ammette (A) -> C . Una tale caratteristica sarebbe equivalente al polimorfismo ad hoc e, in caso affermativo, perché non viene offerta o utilizzata molto / affatto?

Un caso speciale a cui sono particolarmente interessato è la sostituzione dei valori per le funzioni dello stesso tipo di ritorno senza il wrapping in una funzione di identità, ovvero ((A) -> B) -> C ammette B . Se questo esiste ed è meglio conosciuto con un nome diverso, risponderebbe sicuramente alla mia domanda.

    
posta concat 20.12.2016 - 00:06
fonte

2 risposte

2

Non sono a conoscenza di alcun sistema di sottotitoli per il quale A -> C è un sottotipo di (A, B) -> C . Detto questo, non c'è ragione dopo tutto, (a -> c) => (a & b -> c) è un teorema di praticamente tutte le logiche in modo da poter progettare coerentemente un sistema di tipi con quella regola di sottotitoli. Tuttavia, penso che ci siano diversi motivi per cui questo non è mai stato fatto:

  1. Le regole di sottotitoli generalmente includono i costi: rendono l'inferenza di tipo più difficile / più limitata e possono complicare l'implementazione della lingua. Generalmente vuoi evitarli se non riesci a trovare una buona ragione per averli.
  2. Sarebbe incoerente con il sovraccarico di funzionalità che è una funzionalità in molte lingue (Erlang, C #, Java, ...).
  3. Non è chiaro il motivo per cui desideri (A -> C) <: ((A, B) -> C) anziché, ad esempio, (B, A) -> C o B -> A -> C . Questa è la relazione di sottotipizzazione non è naturale come quelle tipiche e sarebbe arbitrariamente scelta tra quelle correlate.

Tutto ciò che viene detto, un sistema di sottotitoli strutturali è molto simile a quello che vuoi. Supponiamo che abbia F = { a : A } -> C e G = { a : A, b : B } -> C . Poiché { a : A, b : B } <: { a : A } , secondo la regola (A <: B) => (B -> C <: A -> C) , abbiamo F <: G . Questo è fondamentalmente ciò che desideri ed esiste già in diversi linguaggi di programmazione come Elm e Typescript.

    
risposta data 20.12.2016 - 02:47
fonte
1

Quindi non è giusto dire che le funzioni di arità inferiori sono sottotipi di quelle più alte. Dopo tutto, non stai parlando solo di funzioni.

Ma se si dispone di un delegato (puntatore a funzione, variabile di funzione, ecc.) che ha una firma di un'arità superiore, dovrebbe essere in grado di svolgere una funzione che soddisfa solo una parte dei parametri. Questo è tipicamente sicuro, anche se non sono sicuro che abbia un nome proprio.

Ci sono alcuni trucchi lì comunque. Il puntatore della funzione continuerà a passare in tutti gli argomenti. La tua implementazione dovrà essere abbastanza intelligente con lo stack delle chiamate per ignorare quegli argomenti, trovare quelli di cui ho bisogno e anche ripulire tutto quando è fatto. Oppure dovrai avvolgere automaticamente la funzione quando la assegni alla variabile in attesa di un'arità più elevata (che quindi aggiunge complessità quando non assegni direttamente la funzione, e lo stesso overhead delle prestazioni di come eseguirla da solo).

    
risposta data 20.12.2016 - 01:53
fonte

Leggi altre domande sui tag