denisshevchenko/ohaskell.guide

View on GitHub
chapters/10-operators.md

Summary

Maintainability
Test Coverage
# Мир операторов

Оператор (англ. operator) — частный случай функции. В предыдущих главах мы уже познакомились с ними, осталось объяснить подробнее.

Вспомним наше самое первое выражение:

```haskell
1 + 2
```

Функция `+` записана в инфиксной (англ. infix) форме, то есть между своими аргументами. Такая запись выглядит естественнее, нежели обычная:

```haskell
(+) 1 2
```

Видите круглые скобки? Они говорят о том, что данная функция предназначена для инфиксной записи. Автор этой функции изначально рассчитывал на инфиксную форму использования `1 + 2`, а не на обычную `(+) 1 2`, именно поэтому имя функции в определении заключено в круглые скобки:

```haskell
(+) :: ...
```

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

Если же имя функции не заключено в круглые скобки, подразумевается, что мы рассчитываем на обычную форму её применения. Однако и в этом случае можно применять её инфиксно, но имя должно заключаться в обратные одинарные кавычки (англ. backtick).

Определим функцию `isEqualTo`, являющуюся аналогом оператора проверки на равенство для двух целочисленных значений:

```haskell
isEqualTo :: Int -> Int -> Bool
isEqualTo x y = x == y
```

При обычной форме её применение выглядело бы так:

```haskell
  ...
  if isEqualTo code1 code2 then ... else ...
  where code1 = 123
        code2 = 124
  ...
```

Но давайте перепишем в инфиксной форме:

```haskell
  ...
  if code1 `isEqualTo` code2 then ... else ...
  where code1 = 123
        code2 = 124
  ...
```

Гораздо лучше, ведь теперь код читается как обычный английский текст:

```haskell
  ...
  if code1 `isEqualTo` code2 ...
  if code1 is equal to code2 ...
  ...
```

Строго говоря, название «оператор» весьма условно, мы можем его и не использовать. Говорить о функции сложения столь же корректно, как и об операторе сложения.

## Зачем это нужно?

Почти все ASCII-символы (а также их всевозможные комбинации) можно использовать в качестве операторов в Haskell. Это даёт нам широкие возможности для реализации различных EDSL (англ. Embedded Domain Specific Language), своего рода «языков в языке». Вот пример:

```haskell
div ! class_ "nav-wrapper" $
  a ! class_ "brand-logo sans" ! href "/" $
    "#ohaskell"
```

Любой, кто знаком с веб-разработкой, мгновенно узнает в этом коде HTML. Это [кусочек кода](https://github.com/denisshevchenko/ohaskell.guide/blob/master/src/CreateHtmlTemplates.hs#L56), строящего HTML-шаблон для веб-варианта данной книги. То что вы видите &mdash; это совершенно легальный Haskell-код, в процессе работы которого генерируется реальный HTML: тег `<div>` с классом `nav-wrapper`, внутри которого лежит `<a>`-ссылка с двумя классами, корневым адресом и внутренним текстом `#ohaskell`.

Идентификаторы `div`, `class_` и `href` &mdash; это имена функций, а символы `!` и `$` &mdash; это операторы, записанные в инфиксной форме. Самое главное, что для понимания этого кода нам абсолютно необязательно знать, где определены все эти функции/операторы и как они работают. Это важная мысль, которую я неоднократно буду повторять в последующих главах:

> Чтобы использовать функции, нам вовсе необязательно знать их внутренности.

А про EDSL запомните, мы с ними ещё встретимся.