Digitare l'inferenza in Golang / Haskell


9

Ho letto che Go in realtà non ha una vera inferenza di tipo nel senso che hanno linguaggi funzionali come ML o Haskell, ma non sono stato in grado di trovare un confronto semplice da comprendere delle due versioni. Qualcuno potrebbe spiegare in termini di base in che modo l'inferenza di tipo in Go differisce dall'inferenza di tipo in Haskell e dai pro / contro di ciascuno?

Risposte:


13

Vedi questa risposta StackOverflow per quanto riguarda l'inferenza del tipo di Go. Non ho familiarità con Go me stesso, ma sulla base di questa risposta sembra una "deduzione del tipo" unidirezionale (prendere in prestito un po 'di teminologia C ++). Significa che se hai:

x := y + z

quindi il tipo di xviene dedotto scoprendo il tipo di y + z, che è una cosa relativamente banale da fare per il compilatore. Per fare questo, i tipi di ye zdevono essere conosciuti a priori : questo potrebbe essere fatto tramite annotazioni sui tipi o dedotto dai letterali loro assegnati.


Al contrario, la maggior parte dei linguaggi funzionali ha inferenza di tipo che utilizza tutte le informazioni possibili all'interno di un modulo (o funzione, se l'algoritmo di inferenza è locale) per derivare il tipo di variabili. Gli algoritmi di inferenza complicata (come Hindley-Milner) spesso implicano una qualche forma di unificazione del tipo (un po 'come risolvere equazioni) dietro le quinte. Ad esempio, in Haskell, se scrivi:

let x = y + z

quindi Haskell può dedurre il tipo non solo xma anche ye zsemplicemente in base al fatto che stai eseguendo l'aggiunta su di essi. In questo caso:

x :: Num a => a
y :: Num a => a
z :: Num a => a

(La minuscola aqui indica un tipo polimorfico , spesso chiamato "generici" in altri linguaggi come C ++. La Num a =>parte è un vincolo per indicare che il asupporto del tipo ha qualche nozione di addizione.)

Ecco un esempio più interessante: il combinatore a punto fisso che consente di definire qualsiasi funzione ricorsiva:

let fix f = f (fix f)

Si noti che da nessuna parte abbiamo specificato il tipo di f, né specificato il tipo di fix, ma il compilatore Haskell può automaticamente capire che:

f :: t -> t
fix :: (t -> t) -> t

Questo dice che:

  • Il parametro fdeve essere una funzione da un tipo arbitrario tallo stesso tipo t.
  • fixè una funzione che riceve un parametro di tipo t -> te restituisce un risultato di tipo t.

4
più precisamente, Haskell può dire che x, y, zsono gli stessi Numtipo Eric, ma possono ancora essere Integers, Doubles, Ratio Integers ... Haskell è disposto a fare una scelta arbitraria tra tipi numerici, ma non per altri typeclasses.
John Dvorak,

7

L'inferenza del tipo in Go è estremamente limitata ed estremamente semplice. Funziona solo in un costrutto di linguaggio (dichiarazione di variabile) e prende semplicemente il tipo del lato destro e lo usa come tipo per la variabile sul lato sinistro.

L'inferenza dei tipi in Haskell può essere usata ovunque, può essere usata per inferire i tipi per l'intero programma. Si basa sull'unificazione, il che significa che (concettualmente) tutti i tipi vengono dedotti "in una volta" e possono influenzarsi a vicenda: in Go, le informazioni sul tipo possono fluire solo dal lato destro di una dichiarazione variabile a sinistra- lato mano, mai nella direzione opposta e mai al di fuori di una dichiarazione variabile; in Haskell, digitare le informazioni scorre liberamente in tutte le direzioni attraverso l'intero programma.

Tuttavia, il sistema di tipi di Haskell è così potente che l'inferenza di tipo può effettivamente non riuscire a inferire un tipo (o più precisamente: le restrizioni devono essere messe in atto in modo che un tipo possa sempre essere dedotto). Il sistema di tipi di Go è così semplice (nessun sottotipo, nessun polimorfismo parametrico) e la sua inferenza così limitata da riuscire sempre.


4
"in Haskell, le informazioni sui tipi scorrono liberamente in tutte le direzioni attraverso l'intero programma": trovo che ciò dia un'ottima intuizione. +1
Giorgio,

Le affermazioni che questa risposta fa nell'ultimo paragrafo sono un po 'fuorvianti. Haskell non ha sottotitoli. Inoltre, il polimorfismo parametrico non causa alcun problema per la completezza dell'inferenza di tipo: Hindley-Milner sul calcolo lambda polimorfico trova sempre il tipo più generale. Haskell non riesce a dedurre i tipi, ma ciò avverrà su sofisticate funzionalità del sistema di tipi come GADT in cui, quando formulato in modo ingenuo, non esiste alcun tipo principale (ovvero "scelta migliore").
Edward Z. Yang,
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.