Condividi tramite


Inferenza del tipo (F#)

In questo argomento viene descritto in che modo avviene l'inferenza dei tipi di valori, variabili, parametri e valori restituiti da parte del compilatore F#.

Concetti generali sull'inferenza del tipo

L'idea di inferenza del tipo è quella di non rendere necessario specificare i tipi dei costrutti F#, ad eccezione di quando questi non possono essere dedotti in modo definitivo dal compilatore. L'omissione di informazioni esplicite sul tipo non significa che F# sia un linguaggio tipizzato dinamicamente o che valori in F# siano tipizzati in modo debole. F# è un linguaggio tipizzato staticamente, ovvero il compilatore deduce un tipo esatto per ogni costrutto durante la compilazione. Se non sono disponibili informazioni sufficienti per consentire al compilatore di dedurre i tipi di ogni costrutto, è necessario fornire informazioni aggiuntive sul tipo, in genere aggiungendo esplicitamente annotazioni del tipo in un punto del codice.

Inferenza di tipi di parametri e di tipi restituiti

In un elenco di parametri, non è necessario specificare il tipo di ogni parametro. F# è tuttavia un linguaggio tipizzato staticamente e pertanto per ogni valore ed espressione è disponibile un tipo definito in fase di compilazione. Per i tipi che non vengono specificati in modo esplicito, il compilatore deriva il tipo in base al contesto. Se il tipo non viene specificato in altro modo, viene considerato come generico. Se nel codice viene utilizzato un valore in modo non consistente e pertanto non è disponibile un unico tipo derivato che soddisfi tutti i tipi di utilizzo di un valore, tramite il compilatore viene segnalato un errore.

Il tipo restituito di una funzione è determinato dal tipo dell'ultima espressione nella funzione.

Nel codice seguente, ad esempio, i tipi dei parametri a e b e il tipo restituito sono tutti considerati come int poiché il valore letterale 100 è di tipo int.

let f a b = a + b + 100

È possibile influenzare l'inferenza del tipo modificando i valori letterali. Se si imposta 100 come tipo uint32 aggiungendo il suffisso u, i tipi di a e b e il valore restituito vengono considerati uint32.

È inoltre possibile influenzare l'inferenza del tipo utilizzando altri costrutti che comportano restrizioni sul tipo, ad esempio funzioni e metodi che possono essere utilizzati solo con un tipo specifico.

È inoltre possibile applicare annotazioni del tipo esplicite a parametri di metodi o funzioni o a variabili nelle espressioni, come illustrato negli esempi seguenti. Se si verificano conflitti tra diversi vincoli, vengono generati errori.

// Type annotations on a parameter.
let addu1 (x : uint32) y =
    x + y

// Type annotations on an expression.
let addu2 x y =
    (x : uint32) + y

È anche possibile specificare in modo esplicito il valore restituito di una funzione fornendo un'annotazione del tipo dopo tutti i parametri.

let addu1 x y : uint32 =
   x + y

Un caso comune in cui un'annotazione del tipo risulta utile su un parametro si verifica nel momento in cui il parametro è un tipo di oggetto e si desidera utilizzare un membro.

let replace(str: string) =
    str.Replace("A", "a")

Generalizzazione automatica

Se il codice della funzione non dipende dal tipo di un parametro, il compilatore considera il parametro come generico. Questo comportamento è detto generalizzazione automatica e può essere molto utile per scrivere codice generico senza aumentare la complessità.

Nella funzione seguente vengono ad esempio combinati due parametri di qualsiasi tipo in una tupla.

let makeTuple a b = (a, b)

Il tipo viene derivato come

'a -> 'b -> 'a * 'b

Informazioni aggiuntive

L'inferenza del tipo viene descritta in modo più dettaglio nella specifica di linguaggio F#.

Vedere anche

Altre risorse

Generalizzazione automatica (F#)