Для моделирования доменов я бы рекомендовал использовать типы с именованными элементами; то есть записи, дискриминационный союз и, возможно, случайный класс или интерфейс.
Структурно, записи и кортежи схожи; в языке алгебраических данных, они оба являются типами продуктов.
Разница в том, что с кортежами порядок значений имеет значение, а роль каждого элемента является неявной.
> (2016, 1, 2) = (2016, 1, 2);;
val it : bool = true
> (2016, 1, 2) = (2016, 2, 1);;
val it : bool = false
В приведенном выше примере вы можете догадаться, что эти кортежи модели датируются, но какие именно? Это второе января 2016 года? Или это первое февраля 2016 года?
с записями, с другой стороны, порядок элементов не имеет значения, потому что вы связываете их, и доступ к ним по имени:
> 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
Это также ясно, когда вы хотите, чтобы вытащить составляющие значения. Вы можете легко получить год от рекордного значения:
> let d = { Year = 2016; Month = 1; Day = 2 };;
val d : Date = {Year = 2016;
Month = 1;
Day = 2;}
> d.Year;;
val it : int = 2016
Это гораздо труднее вытащить значения из кортежа:
> let d = (2016, 1, 2);;
val d : int * int * int = (2016, 1, 2)
> let (y, _, _) = d;;
val y : int = 2016
Предоставленные, для пар, которые вы можете использовать встроенные функции fst
и snd
для доступа к элементам, но для кортежей с тремя или более элементами вы не можете легко получить значения, если вы не сопоставляете шаблон.
Даже если вы определяете пользовательские функции, роль каждого элемента по-прежнему неявно определяется его порядковым номером. Легко получить неправильный порядок значений, если они одного типа.
Итак, для моделирования доменов я всегда предпочитаю явные типы, так что ясно, что происходит.
Корзины никогда не подходят, то?
Кортежи полезны в других контекстах. Если вам нужно использовать ad hoc тип для составления функций, они более подходят, чем записи.
Рассмотрим, в качестве примера, Seq.zip
, который позволяет комбинировать две последовательности:
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
Как вы можете видеть в этом примере, кортежи являются лишь шагом на пути к реальной цели, которая является карта алфавитные значения. Было бы неудобно, если бы нам пришлось определять тип записи, когда мы хотели составлять значения вместе внутри выражения. Кортежи хорошо подходят для этой задачи.
Я бы ответил, но я знаю, что Томас будет делать лучше. IIRC он больше связан с работой с C# и .NET. Если вы чисто в F #, то идите с кортежем. Если вы работаете с другим кодом .NET, переходите к записи. Существуют и другие факторы, например, если они идут с записью, если они не публично идут с кортежем и т. Д. Также перед тем, как вы спросите, также см. [Когда использовать классы, союзы, записи и структуры] (https: // msdn.microsoft.com/en-us/library/dd233205.aspx) в конце ссылки. –
Вы видели всю информацию в теге [F #] (http://stackoverflow.com/tags/f%23/info)? –
[Руководство по дизайну компонентов F #] (http://fsharp.org/specs/component-design-guidelines/) –