Ваше определение Id
имеет ту же семантику, что и следующая:
type T = int | string
Такой тип, который представляет собой сочетание двух других типов, обычно называют «недискриминационным объединением»,Чтобы быть справедливым, есть языки, которые поддерживают недискриминационные объединения (например, TypeScript), но F # не является одним из них.F # является частью семейства языков ML, которые поддерживают дискриминационные союзы.«Дискриминационная» часть означает, что частям объединения необходимо дать отличительное свойство, «дискриминатор», который чаще называют «конструктором».Например:
type T = X of int | Y of string
Здесь X
и Y
являются конструкторами типа T
.Они используются при построении значений, чтобы сказать, какой вариант строится:
let t = X 42
И они используются при сопоставлении с образцом, чтобы сказать, какой вариант ожидается:
let f t = match t with
| X n -> printfn "it's a number: %d" n
| Y s -> printfn "it's a string: %s" s
У вас действительно есть одиниз них в вашем собственном коде - Node
, - поэтому меня немного расстраивает, почему вы допустили эту ошибку с Id
, но не с Node
.
Если вы хотите построить значения Id
как вы делаете в определении i1
и i2
- то есть Id1(1)
, - тогда вам нужно сделать Id
различимым объединением с одним из конструкторов с именем Id1
и приняв int
запараметр.Из остального вашего кода я могу догадаться , что другой конструктор должен быть Id2
и взять string
:
type Id = Id1 of int | Id2 of string
Теперь интересно отметитьявляется то, что, хотя мой пример типа T
выше не будет компилироваться, ваш тип Id
компилируется просто отлично.Почему это так?
Причина в том, что int
и string
имеют неправильную прописную букву (идентификаторы объединенного регистра должны быть в верхнем регистре), но Id1
и Id2
подойдут в этом отношении.Когда вы определяете свой тип как type Id = Id1 | Id2
, это совершенно законно, но эти Id1
и Id2
не имеют никакого отношения к ранее определенным типам Id1
и Id2
.Просто они имеют одно и то же имя, и в F # допускается использовать то же имя, что и в предыдущих определениях.Это называется «затенение».
Ваш тип Id
в итоге получил два конструктора, Id1
и Id2
, оба из которых не имеют параметров.Вот почему компилятор жалуется, когда вы пытаетесь передать 1
в качестве параметра Id1
, когда вы пишете Id1(1)
: « Id1 не является функцией и не может быть применен »