Tipo di inferenza in Golang / Haskell

8

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

    
posta a3onstorm 17.08.2014 - 08:25
fonte

2 risposte

11

Vedi questa risposta StackOverflow riguardante l'inferenza del tipo di Go. Non ho familiarità con Go me, ma sulla base di questa risposta sembra una "deduzione di tipo" a senso unico (per prendere in prestito qualche teminologia C ++). Significa che se hai:

x := y + z

quindi il tipo di x viene dedotto calcolando il tipo di y + z , che è una cosa relativamente banale da fare per il compilatore. Per fare ciò, i tipi di y e z devono essere conosciuti a priori : questo può essere fatto tramite annotazioni di tipo o desunte dai letterali a loro assegnati.

Al contrario, la maggior parte dei linguaggi funzionali ha un'inferenza di tipo che usa 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 complicati (come Hindley-Milner) spesso implicano una qualche forma di tipo unificazione (un po 'come risolvere equazioni) dietro le quinte. Ad esempio, in Haskell, se scrivi:

let x = y + z

allora Haskell può dedurre il tipo non solo x ma anche y e z semplicemente basandosi sul 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 a qui indica un tipo polimorfico , spesso chiamato "generici" in altri linguaggi come il C ++. La parte Num a => è un vincolo per indicare che il supporto di tipo a abbia qualche nozione di addizione.)

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

let fix f = f (fix f)

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

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

Questo dice che:

  • Il parametro f deve essere una funzione da un tipo arbitrario t allo stesso tipo t .
  • fix è una funzione che riceve un parametro di tipo t -> t e restituisce un risultato di tipo t .
risposta data 17.08.2014 - 10:41
fonte
6

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

L'inferenza di tipo in Haskell può essere usata ovunque, può essere usata per dedurre i tipi per l'intero programma. Si basa sull'unificazione, il che significa che (concettualmente) tutti i tipi sono dedotti "alla volta" e possono influenzarsi a vicenda: in Go, le informazioni del tipo possono fluire solo dal lato destro di una dichiarazione di variabile a sinistra- lato della mano, mai nella direzione opposta e mai al di fuori di una dichiarazione variabile; in Haskell, immettere le informazioni 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 fallire per dedurre un tipo (o più precisamente: le restrizioni devono essere messe in posizione in modo che un tipo possa sempre essere dedotto). Il sistema di tipo di Go è così semplice (nessuna sottotipizzazione, nessun polimorfismo parametrico) e la sua inferenza è così limitata da riuscire sempre.

    
risposta data 17.08.2014 - 10:55
fonte

Leggi altre domande sui tag