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

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

функцию и передать её аргументом в другую функцию, которая также может поучаствовать в комбинации

других функций!

5.4 Функции, возвращающие несколько значений

Как было сказано ранее функции, которые возвращают несколько значений, реализованы в Haskell с по-

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

decons :: Stream a -> (a, Stream a)

decons (a :& as) = (a, as)

Здесь функция возвращает сразу два значения. Но всегда ли уместно пользоваться кортежами? Для ком-

позиции функций, которые возвращают несколько значений нам придётся разбирать возвращаемые значения

с помощью сопоставления с образцом и затем использовать эти значения в других функциях. Посудите сами

если у нас есть функции:

f :: a

-> (b1, b2)

g :: b1 -> (c1, c2)

h :: b2 -> (c3, c4)

Мы уже не сможем комбинировать их так просто как если бы это были обычные функции без кортежей.

q x = (\(a, b) -> (g a, h b)) (f x)

В случае пар нам могут прийти на помощь функции first и second:

q = first g . second h . f

Если мы захотим составить какую-нибудь другую функцию из q, то ситуация заметно усложнится. Функ-

ции, возвращающие кортежи, сложнее комбинировать в бесточечном стиле. Здесь стоит вспомнить правило

Unix.

Пишите функции, которые делают одну вещь, но делают её хорошо.

Функции, возвращающие несколько значений | 81

Функция, которая возвращает кортеж пытается сделать сразу несколько дел. И теряет в гибкости, ей

трудно взаимодействовать с другими функциями. Старайтесь чтобы таких функций было как можно меньше.

Если функция возвращает несколько значений, попытайтесь разбить её на несколько, которые возвраща-

ют лишь одно значение. Часто бывает так, что эти значения тесно связаны между собой и такую функцию

не удаётся разбить на несколько составляющих. Если у вас появляется много таких функций, то это повод

задуматься о создании нового типа данных.

Например в качестве точки на плоскости можно использовать пару (Float, Float). В этом случае, если

вы начнёте писать модуль на геометрическую тему у вас появится много функций, которые принимают и

возвращают точки:

rotate

:: Float -> (Float, Float) -> (Float, Float)

norm

:: (Float, Float) -> (Float, Float)

translate

:: (Float, Float) -> (Float, Float) -> (Float, Float)

...

Все они стараются делать несколько дел одновременно, возвращая кортежи. Но мы можем изменить

ситуацию определением новых типов:

data Point

= Point

Float Float

data Vector = Vector Float Float

data Angle

= Angle

Float

Объявления функций станут более краткими и наглядными.