Учебник по Haskell - [38]

Шрифт
Интервал

другую функцию!

Для сокращения числа скобок нам понадобится разобраться в понятии приоритета операции. Так напри-

мер в выражении

> 2 + 3 * 10

32

Мы полагаем, что умножение имеет больший приоритет чем сложение и со скобками это выражение

будет выглядеть так:

> 2 + (3 * 10)

32

Фраза “больший приоритет” означает: сначала умножение потом сложение. Мы всегда можем изменить

поведение по умолчанию с помощью скобок:

> (2 + 3) * 10

50

В Haskell приоритет функций складывается из двух понятий: старшинство и ассоциативность. Старшин-

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

Старшинство используется вычислителем для группировки разных операций, например (+) имеет стар-

шинство 6, а (*) имеет старшинство 7. Поэтому интерпретатор сначала ставит скобки вокруг выражения с

(*), а затем вокруг (+). Считается, что обычное префиксное применение имеет высший приоритет 10. Нельзя

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

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

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 пользователь определяет лишь


Рекомендуем почитать
Уголовное право. Особенная часть

В книге кратко изложены ответы на основные вопросы темы «Уголовное право. Особенная часть». Издание поможет систематизировать знания, полученные на лекциях и семинарах, подготовиться к сдаче экзамена или зачета.Пособие адресовано студентам высших и средних образовательных учреждений, а также всем интересующимся данной тематикой.


Уголовно-исполнительное право

В книге кратко изложены ответы на основные вопросы темы «Уголовно-исполнительное право». Издание поможет систематизировать знания, полученные на лекциях и семинарах, подготовиться к сдаче экзамена или зачета.Пособие адресовано студентам высших и средних образовательных учреждений, а также всем интересующимся данной тематикой.


Самоучитель Adobe Premiere 6.5

Книга посвящена возможностям самого популярного средства цифрового видеомонтажа – Adobe Premiere 6.5. Описываются основные приемы работы с программой, приводятся сведения об управлении проектами и клипами, обсуждаются методы монтажа видео и звука, техника создания титров и добавления спецэффектов, а также освещается процесс окончательного монтирования фильма. На примерах рассматриваются все этапы создания и обработки фильмов для телевидения, видео и мультимедиа.Для широкого круга пользователей.


Финансовое право

В учебном пособии в краткой и доступной форме рассмотрены все основные вопросы, предусмотренные государственным образовательным стандартом и учебной программой по дисциплине «Финансовое право».Книга позволит быстро получить основные знания по предмету, а также качественно подготовиться к зачету и экзамену.Рекомендуется студентам, аспирантам и преподавателям по юридическим, экономическим и управленческим специальностям, а также сотрудникам банков.Автор книги, Шевчук Денис Александрович, имеет опыт преподавания различных дисциплин в ведущих ВУЗах Москвы (экономические, юридические, технические, гуманитарные), два высших образования (экономическое и юридическое), более 30 публикаций (статьи и книги), Член Союза Юристов Москвы, Член Союза Журналистов России, Член Союза Журналистов Москвы, Стипендиат Правительства РФ, опыт работы в банках, коммерческих и государственных структурах (в т.ч.


фгос  ответы

Содержащиеся в пособии контрольно-измерительные материалы (КИМы) для 5 класса, аналогичные материалам ЕГЭ, составлены в соответствии с программой общеобразовательных учреждений по русскому языку и учитывают возрастные особенности учащихся. В конце пособия даны ответы на все варианты тестов, предложены диктанты различных типов.Пособие адресовано учителям, ученикам, их родителям и всем, кому необходимо закрепить и систематизировать знания перед ЕГЭ.


Теория литературы. Чтение как творчество

Цель предлагаемого пособия – систематизировать и обогатить представления о природе, структуре и особенностях художественной литературы как вида искусства, помочь совершенствованию читательского мастерства. Книга снабжена кратким словарем основных литературоведческих понятий и терминов (составлен при участии доцента О.В. Быстровой).Для студентов филологических факультетов, учителей, преподавателей литературы высших и средних учебных заведений.