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

>                     , age :: Int

>                     } deriving (Eq, Show, Read)

Теперь мы можем распечатать запись на экране:

>ghci> mikeD

>Person {firstName = "Michael", lastName = "Diamond", age = 43}

>ghci> "mikeD is: " ++ show mikeD

>"mikeD is: Person {firstName = \"Michael\", lastName = \"Diamond\", age = 43}"

Если бы мы попытались распечатать запись до того, как предусмотрели для типа >Person экземпляры класса >Show, язык Haskell пожаловался бы на то, что он не знает, как представить запись в виде строки. Но после того как мы определили экземпляр класса >Show, всё проясняется.

Класс >Read в чём-то является обратным классом типов для класса >Show. Класс >Show служит для преобразования значений нашего типа в строку, класс >Read нужен для преобразования строк в значения типа. Запомните, что при использовании функции чтения мы должны явно аннотировать тип возвращаемого значения. Если не указать тип результата явно, язык Haskell не сможет угадать, какой тип мы желали бы получить. Чтобы это проиллюстрировать, поместим в файл строку, представляющую некоторого человека, а затем загрузим файл в GHCi:

>mysteryDude = "Person { firstName =\"Майкл\"" ++

>                     ", lastName =\"Даймонд\"" ++

>                     ", age = 45}"

Для большей «читабельности» мы разбили строку на несколько фрагментов. Если теперь необходимо вызвать с этой строкой функцию >read, то потребуется указать тип, который мы ожидаем получить:

>ghci> read mysteryDude :: Person

>Person {firstName = "Майкл", lastName = "Даймонд", age = 45}

Если далее в программе мы используем результат чтения таким образом, что язык Haskell сможет вывести его тип, мы не обязаны использовать аннотацию типа.

>ghci> read mysteryDude == mikeD

>True

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

Если мы попробуем сделать так:

>ghci> read "Just 3" :: Maybe a

то получим сообщение об ошибке: Haskell не в состоянии определить конкретный тип, который следует подставить на место типовой переменной >a. Если же мы точно укажем, что хотим получить >Int, то всё будет прекрасно:

>ghci> read "Just 3" :: Maybe Int

>Just 3

Порядок в суде!

Класс типов >Ord, предназначенный для типов, значения которых могут быть упорядочены, также допускает автоматическое порождение экземпляров. Если сравниваются два значения одного типа, сконструированные с помощью различных конструкторов данных, то меньшим считается значение, конструктор которого определён раньше. Рассмотрим, к примеру, тип >Bool, значениями которого могут быть