Ремонт принтеров, сканнеров, факсов и остальной офисной техники


назад Оглавление вперед




[11]

>val plus = fn : int*int -> int

-3 : bool

Type clach in: 3 : bool Looking for a: bool I have found a: int

-(plus, true) : (int*int -> int) * bool

>(fn, true): (int*int -> int) * bool

-fun id ( x : a ) = x;

>val id = fn : a->a

Заметьте, что в программе переменные типа записываются точно так же, как их выводит ML: апостроф, за которым следует идентификатор.

Равенство является интересным промежуточным случаем. Равенство не является полиморфной функцией в том смысле, в каком таковой является функция append; однако, в противоположность сложению, равенство определено почти для всех типов. Как упоминалось выше, не все типы допускают проверку на равенство, однако для всех типов, допускающих проверку на равенство, существует функция =, которая возвращает true или false в соответствии с тем, равны или нет сравниваемые значения. Поскольку ML может сам определить, допускает тип проверку на равенство или нет, он позволяет использовать равенство "квазиполиморфным" путем. Для этого вводится новый сорт переменных типа, записываемых как "а, которые пробегают множество всех типов, допускающих проверку на равенство. Далее ML следит за тем, требуется или нет, чтобы какой-либо тип допускал проверку на равенство, и отражает этот фактНапример:

-fun member (х, nil) = false

I member (x, hd::tl) = if x=h then true else member(x,tl);

>val member = fn : a * a list -> bool

Вхождения "а в тип функции member указывают, что member может применяться только к аргументам, допускающим проверку на равенство.

2.7 Определения новых типов

ML обладает расширяемой системой типов. Имеется три формы объявления идентификатора как нового конструктора типа.

Простейшей формой является прозрачная привязка к типу, или введение сокращенного наименования типа. Конструктор типа (возможно, с параметрами) определяется как сокращение для некоторого (сложного) типового выражения. Все использования такого конструктора типа полностью эквивалентны использованию вместо него исходного выражения.


-type intpair = int*int;

>type intpair = int*int

-fun f (x : intpair) = let val (l,r)=x in 1 end;

>val f = fn : intpair -> int

-f(3,2);

>3 : int

-type a pair = a*a;

>type a pair = a*a

-type boolpair = bool pair;

>type boolpair = bool pair

Нет никакой разницы между intpair и int*int, поскольку тип intpair определен равным типу int*int. Единственная причина, по которой ML печатает intpair в типе функции f - это то, что этот тип явно был указан при объявлении функции.

Система типов ML может быть также расширена с помощью рекурсивно определяемых типов (или, короче, рекурсивных типов)11. В этой конструкции указывается имя нового типа (возможно, с параметрами) и набор конструкторов значений для построения объектов этого типа. В простейшем случае рекурсивное объявление типа выглядит так:

-datatype color = Red I Blue I Yellow;

>type color

con Red : color con Blue : color con Yellow : color

>Red : color

Приведенное объявление привязывает идентификатор color к новому типу данных, имеющему конструкторы Red, Blue и Yellow12. Этот случай рекурсивного объявления напоминает перечислимые типы в Pascale.

Обратите внимание на то, что ML выводит слово color без последующего знака равенства, подчеркивая этим, что color является новым типом данных: он не совпадает ни с каким ранее определенным типом данных, и поэтому равенство здесь было бы неуместным. Кроме объявления нового типа, приведенная выше конструкция datatype объявляет

11Этот способ определения новых типов предоставляет многообразные возможности и является, пожалуй, наиболее важным в системе типов ML (да и других функциональных языков). Название рекурсивный отражает лишь одну (хотя и наиболее существенную) черту этого способа определения типов. Это название не является повсеместно принятым: так, например, в Haskelle используется термин алгебраический: чаще же всего в англоязычной литературе используется термин datatype (просто копирующий вводящее определение ключевое слово) - однако дословный перевод этого термина (тип данных) в русском языке не отражает особенностей этого понятия. (Прим. перев.)

12Конструкторы без аргументов иногда называют константами.


также три новых конструктора значений. Эти конструкторы выводятся с предшествующим ключевым словом con (а не val), подчеркивая тем самым, что это конструкторы. Введенные конструкторы могут быть использованы для построения образцов при определении функции разбором случаев. Таким образом, рекурсивное определение типа является достаточно сложным: оно одновременно вводит и новый конструктор типа, и новые конструкторы значений.

Рекурсивные определения типов широко используются в ML. Например, можно считать, что встроенный тип bool объявлен как:

-datatype bool = true I false;

>type bool

con true : bool con false: bool

Функции, аргументы которых имеют типы, введенные пользователем, могут быть определены путем разбора случаев так же, как и в случае исходных типов языка. При этом конструкторы значений могут быть использованы в образцах точно так же, как ранее мы использовали nil и : : при определении функций, работающих со списками. Например:

-fun favorite Red = true I favorite Blue = false I favorite Yellow = false;

>val favorite = fn : color->bool

-val color = Red;

>val color = Red : color

-favorite color;

>true : bool

Этот пример также иллюстрирует возможность использования одного и того же идентификатора для нескольких различных целей. Идентификатор color используется и как имя определенного выше типа, и как переменная, привязанная к Red. Такое двойное использование не запрещено (хотя и не рекомендуется, поскольку может привести к затемнению смысла программы), поскольку компилятор всегда может понять из контекста, должно ли в данном месте находится имя типа или имя переменной.

Определяемые пользователем конструкторы значений могут иметь аргументы:

-datatype money = nomoney I coin of int I note of int I

check of string*int;

>type money

con nomoney : money con coin : int->money



[стр.Начало] [стр.1] [стр.2] [стр.3] [стр.4] [стр.5] [стр.6] [стр.7] [стр.8] [стр.9] [стр.10] [стр.11] [стр.12] [стр.13] [стр.14] [стр.15] [стр.16] [стр.17] [стр.18] [стр.19] [стр.20] [стр.21] [стр.22] [стр.23] [стр.24] [стр.25] [стр.26] [стр.27] [стр.28] [стр.29] [стр.30] [стр.31] [стр.32]