Per la modellazione del dominio, si consiglia di utilizzare i tipi con elementi denominati ; cioè, record, unione discriminata e forse la classe o l'interfaccia occasionale.
Strutturalmente, record e tuple sono simili; in termini di tipo di dati algebrici, sono entrambi i tipi di prodotto .
La differenza è che con le tuple, l'ordine dei valori è importante e il ruolo di ogni elemento è implicito.
> (2016, 1, 2) = (2016, 1, 2);;
val it : bool = true
> (2016, 1, 2) = (2016, 2, 1);;
val it : bool = false
Nell'esempio precedente, è possibile indovinare che queste date di modello di tuple, ma quali esattamente? È il secondo di gennaio 2016? O è il primo di febbraio 2016?
con i record, d'altra parte, l'ordine degli elementi non importa, perché li si associa, e accedervi, per nome:
> type Date = { Year : int; Month : int; Day : int };;
type Date =
{Year: int;
Month: int;
Day: int;}
> { Year = 2016; Month = 1; Day = 2 } = { Year = 2016; Day = 2; Month = 1 };;
val it : bool = true
E 'anche più chiaro quando si vuole tirare fuori il valori costitutivi. Si può facilmente ottenere l'anno da un valore record di:
> let d = { Year = 2016; Month = 1; Day = 2 };;
val d : Date = {Year = 2016;
Month = 1;
Day = 2;}
> d.Year;;
val it : int = 2016
E 'molto più difficile da tirare i valori di una tupla:
> let d = (2016, 1, 2);;
val d : int * int * int = (2016, 1, 2)
> let (y, _, _) = d;;
val y : int = 2016
scontato, per le coppie, è possibile utilizzare le funzioni incorporate fst
e snd
per accedere agli elementi, ma per le tuple con tre o più elementi, non è possibile ottenere facilmente i valori a meno che il modello non corrisponda.
Anche se si definiscono funzioni personalizzate, il ruolo di ogni elemento è ancora implicitamente definito dal suo ordinale. È facile ottenere l'ordine dei valori errati se sono dello stesso tipo.
Quindi, per la modellazione del dominio, preferisco sempre i tipi espliciti, in modo che sia chiaro cosa sta succedendo.
Le tuple non sono mai appropriate, quindi?
Le tuple sono utili in altri contesti. Quando è necessario utilizzare un tipo ad hoc per comporre funzioni, sono più appropriate dei record.
Si consideri, ad esempio, Seq.zip
, che consente di combinare due sequenze:
let alphalues = Seq.zip ['A'..'Z'] (Seq.initInfinite ((+) 1)) |> Map.ofSeq;;
val alphalues : Map<char,int> =
map
[('A', 1); ('B', 2); ('C', 3); ('D', 4); ('E', 5); ('F', 6); ('G', 7);
('H', 8); ('I', 9); ...]
> alphalues |> Map.find 'B';;
val it : int = 2
Come si può vedere in questo esempio, tuple sono solo un passo verso il vero obiettivo, che è una mappa di valori alfabetici. Sarebbe imbarazzante se dovessimo definire un tipo di record ogni volta che volessimo comporre valori all'interno di un'espressione. Le tuple sono adatte per questo compito.
Vorrei rispondere ma so che Tomas farà di meglio. IIRC ha più a che fare con il lavoro con C# e .NET. Se sei puramente in F #, vai con la tupla. Se stai lavorando con un altro codice .NET, vai con il record. Ci sono altri fattori, ad esempio se è grande andare con un record, se non è pubblico andare con una tupla, ecc. Inoltre prima di chiedere anche di vedere [Quando usare classi, unioni, record e strutture] (https: // msdn.microsoft.com/en-us/library/dd233205.aspx) alla fine del collegamento. –
Hai visto tutte le informazioni nel [tag F #] (http://stackoverflow.com/tags/f%23/info)? –
[Le linee guida per la progettazione dei componenti F #] (http://fsharp.org/specs/component-design-guidelines/) –