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

Примите во внимание, что тип, экземпляр для которого вы пытаетесь создать, заменит параметр в декларации класса. Параметр >a из декларации >class Eq a where будет заменён конкретным типом при создании экземпляра; попытайтесь в уме заменить тип также и в декларациях функций. Сигнатура >(==) :: Maybe –> Maybe –> Bool не имеет никакого смысла, но сигнатура >(==) :: (Eq m) => Maybe m –> Maybe m –> Bool имеет. Впрочем, это нужно только для упражнения, потому что оператор >== всегда будет иметь тип >(==) :: (Eq a) => a –> a –> Bool независимо от того, какие экземпляры мы порождаем.

О, и ещё одна классная фишка! Если хотите узнать, какие экземпляры существуют для класса типов, вызовите команду >: info в GHCi. Например, выполнив команду >:info Num, вы увидите, какие функции определены в этом классе типов, и выведете список принадлежащих классу типов. Команда >:info также работает с типами и конструкторами типов. Если выполнить >:info Maybe, мы увидим все классы типов, к которым относится тип >Maybe. Вот пример:

>ghci> :info Maybe

>data Maybe a = Nothing | Just a -- Defined in Data.Maybe

>instance Eq a => Eq (Maybe a) -- Defined in Data.Maybe

>instance Monad Maybe -- Defined in Data.Maybe

>instance Functor Maybe -- Defined in Data.Maybe

>instance Ord a => Ord (Maybe a) -- Defined in Data.Maybe

>instance Read a => Read (Maybe a) -- Defined in GHC.Read

>instance Show a => Show (Maybe a) -- Defined in GHC.Show

Класс типов «да–нет»

В языке JavaScript и в некоторых других слабо типизированных языках вы можете поместить в оператор >if практически любые выражения. Например, все следующие выражения правильные:

>if (0) alert("ДА!") else alert("НЕТ!")


>if ("") alert ("ДА!") else alert("НЕТ!")


>if (false) alert("ДА!") else alert("НЕТ!)

и все они покажут >НЕТ!".

Если вызвать

>if ("ЧТО") alert ("ДА!") else alert("НЕТ!")

мы увидим >"ДА!", так как язык JavaScript рассматривает непустые строки как вариант истинного значения.



Несмотря на то, что строгое использование типа >Bool для булевских выражений является преимуществом языка Haskell, давайте реализуем подобное поведение. Просто для забавы. Начнём с декларации класса:

>class YesNo a where

>   yesno :: a –> Bool

Довольно просто. Класс типов >YesNo определяет один метод. Эта функция принимает одно значение некоторого типа, который может рассматриваться как хранитель некоей концепции истинности; функция говорит нам, истинно значение или нет. Обратите внимание: из того, как мы использовали параметр >a в функции, следует, что он должен быть конкретным типом.

Теперь определим несколько экземпляров. Для чисел, так же как и в языке JavaScript, предположим, что любое ненулевое значение истинно, а нулевое – ложно.