Это не так, но это в основном только по причинам, связанным с синтаксисом c:
*
и ->
являются ключевыми словами, а не идентификаторами (за исключением несвязанного использования *
в качестве идентификатора, например, 3 * 4 = 12
). - Мы пишем
int * real
и int -> real
вместо (int, real) *
и (int, real) ->
. - Конструктор типа имеет фиксированное число: параметры (например,
list
всегда принимает один параметр - мы не можем записать (int, real) list
- и int
всегда не принимает ни одного), но int * real * char * string
- это 4-кортеж. (Другими словами: *
«перегружен» для любого типа n с набором n ≥ 2. Так что это похоже на бесконечно много конструкторов типа, скорее чем один.)
Но я не думаю, что есть какая-либо причина, по которой это должно быть таким. Можно представить версию Standard ML в параллельной вселенной, в которой:
- определяет не
*
и ->
как зарезервированные слова, а как идентификаторы в исходной базе (аналогично ref
или int
). - позволяет конструкторам типов быть инфиксными (аналогично тому, как
3 + 4
означает op+ (3, 4)
) и объявлять *
и ->
как таковые. - не поддерживал нотацию
*
для продуктов трех и более типов, а интерпретировал int * real * char * string
как ((int * real) * char) * string
. (В нашей вселенной 'a * 'b * … * 'n
- это просто синтактический c сахар для { 1: 'a, 2: 'b, …, 14: 'n }
; возможно, в параллельной вселенной, которая не считается очень полезной для продуктов трех или более типов?)
На самом деле даже в нашей собственной вселенной мы можем написать:
type ('a, 'b) pair = 'a * 'b
type ('a, 'b, 'c) triple = 'a * 'b * 'c
type ('a, 'b) function = 'a -> 'b
, который создает конструкторы типов pair
, triple
и function
, так что (int, real) pair
является синонимом int * real
, (int, real, char) triple
является синонимом int * real * char
, а (int, real) function
является синонимом int -> real
. (Не то, чтобы кто-то хотел этого.)