52700.fb2 Учебник по Haskell - читать онлайн бесплатно полную версию книги . Страница 151

Учебник по Haskell - читать онлайн бесплатно полную версию книги . Страница 151

words :: String -> [String]

-- возвращает True только в том случае, если

-- первый список полностью содержится во втором

isInfixOf :: Eq a => [a] -> [a] -> Bool

• Классы Functor и Applicative замкнуты относительно композиции. Это свойство говорит о том, что

композиция (аппликативных) функторов снова является (аппликативным) функтором. Докажите это!

Пусть дан тип, который описывает композицию двух типов:

newtype O f g a = O { unO :: f (g a) }

Определите экземпляры классов:

instance (Functor f, Functor g) => Functor (O f g) where ...

instance (Applicative f, Applicative g) => Applicative (O f g) where ...

Подсказка: если совсем не получается, ответ можно подсмотреть в библиотеке TypeCompose. Но пока мы

не знаем как устанавливать библиотеки и где они живут, всё-таки попытайтесь решить это упражнение

самостоятельно.

Упражнения | 141

Глава 9

Редукция выражений

В этой главе мы поговорим о том как вычисляются программы. В самом начале мы говорили о том, что

процесса вычисления значений нет. В том смысле, что у нас нет новых значений, у нас ничего не меняется,

мы лишь расшифровываем синонимы значений.

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

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

мы определяем в типах. Так например мы можем определить тип:

data Nat = Zero | Succ Nat

Этим типом мы определяем множество допустимых значений. В данном случае это цепочки конструкто-

ров Succ, которые заканчиваются конструктором Zero:

Zero, Succ Zero, Succ (Succ Zero), ...

Затем начинаем давать им новые имена, создавая константы (простые имена-синонимы)

zero

= Zero

one

= Succ zero

two

= Succ one

и функции (составные имена-синонимы):

foldNat :: a -> (a -> a) -> Nat -> a

foldNat z

s

Zero

= z

foldNat z

s

(Succ n)

= s (foldNat z s n)

add a = foldNat a

Succ

mul a = foldNat one (add a)

Затем мы передаём нашу программу на проверку компилятору. Мы просим у него проверить не создаём

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

значение, которое не вписывается в наши типы. Например если мы где-нибудь попробуем составить выра-