Изучай Haskell во имя добра! (Липовача) - страница 86

. Явное указание типа может понадобиться, если мы, к примеру, хотим, чтобы значение >Just 3 имело тип >Maybe Int. По умолчанию Haskell выведет тип >(Num a) => Maybe a. Воспользуемся явным аннотированием типа:

>ghci> Just 3 :: Maybe Int

>Just 3

Может, вы и не знали, но мы использовали тип, у которого были типы-параметры ещё до типа >Maybe. Этот тип – список. Несмотря на то что дело несколько скрывается синтаксическим сахаром, конструктор списка принимает параметр для того, чтобы создать конкретный тип. Значения могут иметь тип >[Int], >[Char], >[[String]], но вы не можете создать значение с типом >[].

ПРИМЕЧАНИЕ. Мы называем тип конкретным, если он вообще не принимает никаких параметров (например, >Int или >Bool) либо если параметры в типе заполнены (например, >Maybe Char). Если у вас есть какое-то значение, у него всегда конкретный тип.

Давайте поиграем с типом >Maybe:

>ghci> Just "Ха-ха"

>Just "Ха-ха"

>ghci> Just 84

>Just 84

>ghci> :t Just "Ха-ха"

>Just "Ха-ха" :: Maybe [Char]

>ghci> :t Just 84

>Just 84 :: (Num t) => Maybe t

>ghci> :t Nothing

>Nothing :: Maybe a

>ghci> Just 10 :: Maybe Double

>Just 10.0

Типы-параметры полезны потому, что мы можем с их помощью создавать различные типы, в зависимости от того, какой тип нам надо хранить в нашем типе данных. К примеру, можно объявить отдельные Maybe-подобные типы данных для любых типов:

>data IntMaybe = INothing | IJust Int


>data StringMaybe = SNothing | SJust String


>data ShapeMaybe = ShNothing | ShJust Shape

Более того, мы можем использовать типы-параметры для определения самого обобщённого >Maybe, который может содержать данные вообще любых типов!

Обратите внимание: тип значения >Nothing>Maybe a. Это полиморфный тип: в его имени присутствует типовая переменная – конкретнее, переменная >a в типе >Maybe a. Если некоторая функция принимает параметр типа >Maybe Int, мы можем передать ей значение >Nothing, так как оно не содержит значения, которое могло бы этому препятствовать. Тип >Maybe a может вести себя как >Maybe Int, точно так же как значение >5 может рассматриваться как значение типа >Int или >Double. Аналогичным образом тип пустого списка – это >[a]. Пустой список может вести себя как список чего угодно. Вот почему можно производить такие операции, как >[1,2,3] ++ [] и >["ха","ха","ха"] ++ [].

Параметризовать ли машины?

Когда имеет смысл применять типовые параметры? Обычно мы используем их, когда наш тип данных должен уметь сохранять внутри себя любой другой тип, как это делает >Maybe a. Если ваш тип – это некоторая «обёртка», использование типов-параметров оправданно. Мы могли бы изменить наш тип данных