Что означает type X = Y of Z
в F#? В частности, имеет ли токен Y какую-либо материальную цель? Если я хочу выразить тот факт, что X является типом, поддерживаемым нижележащим типом Z, зачем мне Y в этом выражении?
Согласно https://learn.microsoft.com/en-us/dotnet/fsharp/language-reference/keyword-reference, ключевое слово of
используется для выражения одного из них:
Строго говоря, согласно документам, type X = Y of Z
не попадает ни в одну из трех вышеперечисленных категорий.
|
.Таким образом, похоже, что type X = Y of Z
является недопустимым синтаксисом, хотя он повсеместно используется в https://fsharpforfunandprofit.com/posts/conciseness-type-definitions/. Очень озадачивает - неужели документы неточны?
Вопреки вашей интуиции, такая декларация, по сути, является дискриминационным союзом - с одним падежом. Да, размеченные объединения только с одним регистром абсолютно законны и иногда используются для обеспечения безопасности типов или для сокрытия деталей реализации.
Если вы не хотите, чтобы там был этот дополнительный Y
, это также законно:
type X = Z
Это называется "псевдоним типа". Его преимущество перед размеченным объединением заключается в потреблении ресурсов (как производительности, так и памяти), но его недостаток в том, что он не обеспечивает никакой дополнительной безопасности, потому что X
оказывается эквивалентным и взаимозаменяемым с Z
во всех контекстах.
Это не синтаксис Discriminated Union, потому что в нем отсутствует канал | характер.
Можно опустить первую вертикальную черту в размеченном объединении:
type DU = A of int | B
Это плохой стиль для стандартных многострочных определений, но может подойти для однострочных. В вашем примере есть только один случай, поэтому можно полностью опустить трубу, что, по общему признанию, вызывает путаницу. Включение полосы улучшило бы ясность: type X = | Y of Z
В
type X = Y of Z
имеет ли токен Y какую-либо материальную цель?
Y используется для устранения неоднозначности между случаями и для сопоставления с данными. Если в будущем, вероятно, будет больше случаев, то имеет смысл иметь эти леса для сопоставления. Если вы знаете, что будет только один случай, то DU — не самый подходящий тип, поскольку запись type X = { Y: Z }
— это более простая конструкция, которая достигает той же цели.
Просто помните, что если
Z
не является ранее определенным типом, тоtype X = Z
на самом деле является DU с одним регистром и пустым регистром. Не очень полезно! Но это можно сделать случайно, например. в случаеtype Duration = TimeSpan
если вы забудетеopen System
.