Главная » Haskell » Модуль Arrow

0

содержит базовое определение стрелки, основанное на теоретической работе [9], а также  отчасти на работе [21]. В  этих статьях описаны правила, которым должны удовлетворять описываемые в модуле комбинаторы. Дополнительные материалы по стрелкам могут быть найдены по адресу в интернете http://www.haskell.org/arrows/.

Использование:

import Control.Arrow

Главный класс модуля, который описывает интерфейс стрелки, выглядит следующим образом:

class Arrow  a where

arr    :: (b  ->  c)  ->  a b c pure      ::  (b  ->  c) ->  a b c

(>>>)    :: a b c  ->  a c  d  ->  a b d first :: a b c  ->  a (b, d)  (c, d) second  :: a b c  ->  a (d, b)  (d,  c)

(***) :: a b c  ->  a b’ c’ ->  a (b, b’)  (c, c’) (&&&)   :: a b c  ->  a b c’ ->  a  b  (c, c’)

Это основной класс для описания стрелок. Любой его экземпляр должен в обязательном порядке определять метод arr или метод pure, которые являются синонимами. Другие комбинаторы класса выражены через базовый метод, но могут быть переопределены для достижения требуемых эффектов.

Метод arr втягивает функцию в стрелку. Программист обязательно должен определить либо этот метод, либо метод pure при разработке экземпляров класса Arrow. Метод pure является всего лишь синонимом для большего соответствия теории.

Операция (>>>) определяет композицию стрелок слева направо.

Метод first передаёт первый компонент входа через аргумент стрелки, после чего без изменений копирует остаток в выход. Метод second является зеркальной копией метода first для второго компонента входа.

Операция (***) разбивает вход для двух аргументов стрелки и комбинирует их выходы. Необходимо отметить, что в общем виде этот метод не является функтором. В целях оптимизации этот метод нужно  переопределять для конкретных типов. Также и операция (&&&) предназначена для передачи входа в оба аргумента стрелки и последующего комбинирования выходов. Эта операция тоже должна быть переопределена для конкретных типов, хотя для неё и имеется реализация по умолчанию.

Экземплярами класса Arrow являются типы:  (->)  и Kleisli,  причём тип

Kleisli определён в этом модуле как

newtype Kleisli m   a b

= Kleisli

{

runKleisli :: (a  ->  m   b)

}

Этот изоморфный тип определяет стрелку Клейсли для монад.

Для класса Arrow определён ряд утилитарных функций. К числу таких функций относятся следующие.

Функция: returnA

Описание: стрелка тождества, которая играет роль метода return для стрелок.

Определение:

returnA ::  Arrow  a => a b  b returnA = arr  id

Функция: (?>>)

Описание: прекомпозиция с чистой функцией.

Определение:

infixr 1 ^>>

(^>>)   :: Arrow  a => (b  ->  c) ->  a  c  d ->  a b d f ^>> a = arr f >>> a

Функция: (>>?)

Описание: посткомпозиция с чистой функцией.

Определение:

infixr 1 >>^

(>>^)   :: Arrow  a => a b c  ->  (c ->  d)  ->  a b d a >>^ f = a >>> arr f

Функция: (<<<)

Описание: композиция стрелок справа налево.

Определение:

infixr 1 <<<

(<<<)  :: Arrow  a => a c  d ->  a  b  c  ->  a b d f <<< g = g >>> f

Функция: (<<?)

Описание: прекомпозиция с чистой функцией (справа налево).

Определение:

infixr  1  <<^

(<<^)   :: Arrow  a => a c  d ->  (b  ->  c)  ->  a b d a <<^ f = a <<< arr f

Функция: (?<<)

Описание: посткомпозиция с чистой функцией (справа налево).

Определение:

infixr  1  ^<<

(^<<)   :: Arrow  a => (c ->  d)  ->  a b c  ->  a b d f ^<< a = arr f <<< a

Дополнительно в модуле Arrow описаны вспомогательные классы,  которые конкретизируют области применения стрелок. К таковым классам относятся следующие.

Класс: ArrowZero

Описание: определяет операцию получения нулевого элемента для моноидов.

Определение:

class Arrow  a => ArrowZero  a where zeroArrow  :: a b  c

Экземпляры: Kleisli.

Класс: ArrowPlus

Описание: определяет операцию сложения для моноидов.

Определение:

class ArrowZero  a => ArrowPlus  a where (<+>)  :: a b c  ->  a  b  c  ->  a b c

Экземпляры: Kleisli.

Класс: ArrowChoice

Описание: определяет функции для осуществления ветвления алгоритма в тех стрелках, которые  поддерживают ветвление. Имеет  методы, которые  соответствуют ключевым словам if и case. Любой экземпляр этого класса в обязательном порядке должен определять метод left.

Определение:

class Arrow  a =>  ArrowChoice  a where

left :: a b c  ->  a (Either b d)  (Either c  d) right :: a b c  ->  a  (Either d b)  (Either d c)

(+++)  :: a b c  ->  a b’ c’ ->  a (Either b b’)  (Either c  c’) (|||)  :: a b d ->  a c  d ->  a  (Either b c) d

Метод left «скармливает» помеченные входы аргументу стрелки, передавая остаток без изменений  в выход. Метод right является зеркальным отражением метода left. Оба этих метода могут быть переопределены в экземплярах для более эффективной  работы с конкретными типами данных.

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

Экземплярами класса являются типы: (->)  и Kleisli.

Класс: ArrowApply

Описание: интерфейс для стрелок, у которых имеется операция приложения.

Определение:

class Arrow  a =>  ArrowApply  a where app  :: a (a  b c, b)  c

Метод app предназначен, соответственно, для приложения стрелок.

Экземплярами класса являются типы: (->)  и Kleisli.

Класс: ArrowLoop

Описание: интерфейс для стрелок, поддерживающих циклы. Единственный  метод loop выражает вычисления, в которых выходное значение передаётся снова на вход, даже если вычисления производятся один раз.

Определение:

class Arrow  a =>  ArrowLoop a where loop :: a (b, d)  (c,  d)  ->  a b c

Экземплярами класса являются типы: (->)  и Kleisli.

Остаётся отметить, что  за этот модуль в поставке  языка  Haskell отвечает Р.  Патерсон, с которым  можно  связаться по  адресу электронной почты ross@soi.city.ac.uk.

Источник: Душкин Р. В., Справочник по языку Haskell. М.: ДМК Пресс, 2008. 544 с., ил.

По теме:

  • Комментарии