Читаем Учебник по Haskell полностью

задать приоритет выше применения, это значит, что операция “пробел” будет всегда выполняться первой.

Ассоциативность используется для группировки одинаковых операций, например мы видим:

1+2+3+4

Как нам быть? Мы можем группировать скобки слева направо:

((1+2)+3)+4

Или справа налево:

1+(2+(3+4))

Ответ на этот вопрос даёт ассоциативность, она бывает левая и правая. Например операции (+) (-) и (*)

являются лево-ассоциативными, а операция возведения в степень (^) является право-ассоциативной.

1 + 2 + 3 == (1 + 2) + 3

1 ^ 2 ^ 3 ==

1 ^ (2 ^ 3)

Приоритет функции можно узнать в интерпретаторе с помощью команды :i:

*FunNat> :m Prelude

Prelude> :i (+)

class (Eq a, Show a) => Num a where

(+) :: a -> a -> a

...

-- Defined in GHC.Num

infixl 6 +

Prelude> :i (*)

class (Eq a, Show a) => Num a where

...

(*) :: a -> a -> a

...

-- Defined in GHC.Num

infixl 7 *

Prelude> :i (^)

(^) :: (Num a, Integral b) => a -> b -> a

-- Defined in GHC.Real

infixr 8 ^

76 | Глава 5: Функции высшего порядка

Приоритет указывается в строчках infixl 6 + и infixl 7 *. Цифра указывает на старшинство операции,

а суффикс l (от англ. left – левая) или r (от англ. right – правая) на ассоциативность.

Если мы создали свою функцию, мы можем определить для неё ассоциативность. Для этого мы пишем в

коде:

module Fixity where

import Prelude(Num(.. ))

infixl 4 ***

infixl 5 +++

infixr 5 ‘neg‘

(***) = (*)

(+++) = (+)

neg

= (-)

Мы ввели новые операции и поменяли старшинство операций сложения и умножения местами и изме-

нили ассоциативность у вычитания. Проверим в интерпретаторе:

Prelude> :l Fixity

[1 of 1] Compiling Fixity

( Fixity. hs, interpreted )

Ok, modules loaded: Fixity.

*Fixity> 1 + 2 * 3

7

*Fixity> 1 +++ 2 *** 3

9

*Fixity> 1 - 2 - 3

-4

*Fixity> 1 ‘neg‘ 2 ‘neg‘ 3

2

Посмотрим как это вычислялось:

1

+

2

*

3

==

1

+

(2

*

3)

1

+++

2

*** 3

==

(1

+++

2)

***

3

1

-

2

-

3

==

(1

-

2)

-

3

1 ‘neg‘ 2 ‘neg 3‘ ==

1 ‘neg‘ (2

‘neg‘ 3)

Также в Haskell есть директива infix это тоже самое, что и infixl.

Приоритет функции композиции

Посмотрим на приоритет функции композиции:

Prelude> :i (. )

(. ) :: (b -> c) -> (a -> b) -> a -> c

-- Defined in GHC.Base

infixr 9 .

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

стиле. Такая функция похожа на конвейер функций:

fun a = fun1 a . fun2 (x1 + x2) . fun3 . (+x1)

Приоритет функции применения

Теперь посмотрим на полное определение функции применения:

infixr 0 $

($) :: (a -> b) -> a -> b

f $ x

=

f x

Ответ на вопрос о полезности этой функции кроется в её приоритете. Ей назначен самый низкий прио-

ритет. Она будет исполняться в последнюю очередь. Очень часто возникают ситуации вроде:

Приоритет инфиксных операций | 77

foldNat zero succ (Succ b) = succ (foldNat zero succ b)

С помощью функции применения мы можем переписать это определение так:

foldNat zero succ (Succ b) = succ $ foldNat zero succ b

Если бы мы написали без скобок:

... = succ foldNat zero succ b

То выражение было бы сгруппировано так:

... = (((succ foldNat) zero) succ) b

Но поскольку мы поставили барьер в виде операции ($) с низким приоритетом, группировка скобок

произойдёт так:

... = (succ $ ((foldNat zero) succ) b)

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

несколько вложенных функций на конце выражения:

xs :: [Int]

xs = reverse $ map ((+1) . (*10)) $ filter even $ ns 40

ns :: Int -> [Int]

ns 0

= []

ns n

= n : ns (n - 1)

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

потом применяем два арифметических действия ко всем элементам списка, затем переворачиваем список.

Проверим работает ли это в интерпретаторе, заодно поупражняемся в композиционном стиле:

Prelude> let ns n = if (n == 0) then [] else n : ns (n - 1)

Prelude> let even x = 0 == mod x 2

Prelude> let xs = reverse $ map ((+1) . (*10)) $ filter even $ ns 20

Prelude> xs

[21,41,61,81,101,121,141,161,181,201]

Если бы не функция применения нам пришлось бы написать это выражение так:

xs = reverse (map ((+1) . (*10)) (filter even (ns 40)))

5.3 Функциональный калькулятор

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

За счёт развитых средств составления новых функций в Haskell пользователь определяет лишь

базовые функции, получая остальные “на лету” применением двух-трёх операций, это выглядит

примерно как (2+3)*5, где вместо чисел стоят базовые функции, а операции + и * составляют

новые функции из простейших.

Такие обобщённые функции как id, const, (. ), map filter позволяют очень легко комбинировать различ-

ные функции. Бесточечный стиль записи функций превращает функции в простые значения или значения-

Перейти на страницу:

Похожие книги

1С: Бухгалтерия 8 с нуля
1С: Бухгалтерия 8 с нуля

Книга содержит полное описание приемов и методов работы с программой 1С:Бухгалтерия 8. Рассматривается автоматизация всех основных участков бухгалтерии: учет наличных и безналичных денежных средств, основных средств и НМА, прихода и расхода товарно-материальных ценностей, зарплаты, производства. Описано, как вводить исходные данные, заполнять справочники и каталоги, работать с первичными документами, проводить их по учету, формировать разнообразные отчеты, выводить данные на печать, настраивать программу и использовать ее сервисные функции. Каждый урок содержит подробное описание рассматриваемой темы с детальным разбором и иллюстрированием всех этапов.Для широкого круга пользователей.

Алексей Анатольевич Гладкий

Программирование, программы, базы данных / Программное обеспечение / Бухучет и аудит / Финансы и бизнес / Книги по IT / Словари и Энциклопедии
1С: Управление торговлей 8.2
1С: Управление торговлей 8.2

Современные торговые предприятия предлагают своим клиентам широчайший ассортимент товаров, который исчисляется тысячами и десятками тысяч наименований. Причем многие позиции могут реализовываться на разных условиях: предоплата, отсрочка платежи, скидка, наценка, объем партии, и т.д. Клиенты зачастую делятся на категории – VIP-клиент, обычный клиент, постоянный клиент, мелкооптовый клиент, и т.д. Товарные позиции могут комплектоваться и разукомплектовываться, многие товары подлежат обязательной сертификации и гигиеническим исследованиям, некондиционные позиции необходимо списывать, на складах периодически должна проводиться инвентаризация, каждая компания должна иметь свою маркетинговую политику и т.д., вообщем – современное торговое предприятие представляет живой организм, находящийся в постоянном движении.Очевидно, что вся эта кипучая деятельность требует автоматизации. Для решения этой задачи существуют специальные программные средства, и в этой книге мы познакомим вам с самым популярным продуктом, предназначенным для автоматизации деятельности торгового предприятия – «1С Управление торговлей», которое реализовано на новейшей технологической платформе версии 1С 8.2.

Алексей Анатольевич Гладкий

Финансы / Программирование, программы, базы данных