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

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

значения из конструктора Int будут храниться прямо в конструкторе PairInt:

nil = []

-- глобальный объект (не в счёт)

let p

= PairInt 1 2

-- 3 слова

val = Cons p nil

-- 3 слова

in

val

------------

-- 6 слов

Так мы сократим размер до 6 N. Но мы можем пойти ещё дальше. Если этот тип является ключевым

типом нашей программы и мы расчитываем на то, что в нём будет хранится много значений мы можем

создать специальный список для таких пар и распаковать значение списка:

data ListInt = ConsInt {-# UNPACK #-} !PairInt

| NilInt

nil = NilInt

let val = ConsInt 1 2 nil

-- 4 слова

in

val

-----------

-- 4 слова

Значение будет встроено дважды и получится, что у нашего нового конструктора Cons уже три поля.

Отметим, что эта прагма имеет смысл лишь при включённом флаге оптимизации -O или выше. Если мы

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

функций вроде

Оптимизация программ | 177

sumPair :: PairInt -> Int

sumPair (Pair a b) = a + b

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

компилятор сначала запакует их в конструктор I# и затем применит функцию +, в которой опять распакует

их, сложит и затем, снова запаковав, вернёт результат.

Компилятор автоматически запаковывает все такие значения при передаче в ленивую функцию, это мо-

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

встраивании. Это необходимо учитывать. В таких случая проводите профилирование, убедитесь в том, что

оптимизация привела к повышению эффективности.

В стандартных библиотеках предусмотрено много незапакованных типов. Например это специальные

кортежи. Они пишутся с решётками:

newtype ST s a = ST (STRep s a)

type STRep s a = State# s -> (# State# s, a #)

Это определение типа ST. Специальные кортежи используются для возврата нескольких значений напря-

мую, без создания промежуточного кортежа в куче. В этом случае значения будут сохранены в регистрах

или на стеке. Для использования специальных значений необходимо активировать расширения MagicHash и

UnboxedTuples

Разработчики различных библиотек могут предоставлять несколько вариантов своих данных: ленивые

версии и незапакованные. Например в ST-массив незапакованных значений STUArray s i a эквивалентен

массиву значений в C. В таком массиве можно хранить лишь примитивные типы.

10.8 Краткое содержание