Символ *
используется для разделения элементов кортежа в определениях типов данных. Символ ,
используется для разделения переменных типа в параметрическом типе, который имеет более одной переменной.
Например, в Student of name * age * class
мы определяем конструктор с тремя аргументами. Чтобы создать значение с помощью этого конструктора, мы передаем аргументы в виде кортежа Student ("Jon",21,"CS")
. Обратите внимание, что мы использовали запятую для разделения аргументов кортежа.
В вашем примере тип ('k,'v) tree
является параметрическим с двумя переменными типа. Следовательно, мы должны обращаться к нему всегда, как это (Не ('k * 'v) tree
, а ('k,'v) tree
)
Правильное определение должно выглядеть следующим образом
type ('k,'v) tree =
| Leaf
| Node of 'k * 'v * ('k,'v) tree * ('k,'v) tree
Обратите внимание, что круглые скобки вокруг ('k * 'v)
имеют специальную семантику, поскольку ниже определяется конструктор с четырьмя аргументами (ключ, значение, lhs, rhs),
| Node of 'k * 'v * ('k,'v) tree * ('k,'v) tree
при следующих
| Node of ('k * 'v) * ('k,'v) tree * ('k,'v) tree
Определяет конструктор с тремя аргументами, например, Node (data,lhs,rhs)
, где data
представляется в виде пары (key,value)
. Представление с 3 аргументами будет использовать больше памяти, потому что каждая пара (key,value)
будет храниться в коробочном представлении, вне дерева. Или графически 1 ,
4 arguments 3 arguments
representation representation
(5 words/node) (7 words/node)
+--------+ +--------+
| header | | header |
+--------+ +--------+ +--------+
| key | | data |---->| header |
+--------+ +--------+ +--------+
| value | vs. | left | | key |
+--------+ +--------+ +--------+
| left | | right | | value |
+--------+ +--------+ +--------+
| right |
+--------+
1) в реальной реализации указатель data
будет фактически указывать на key
, т. Е. На первое поле в штучной упаковке, но я думаю, что концептуально лучше игнорировать эта реализация подробно.