Haskell Language
Стрелы
Поиск…
Функциональные композиции с несколькими каналами
Arrow , смутно говоря, является классом морфизмов, которые составляют подобные функции, как с последовательным составом, так и с «параллельным составом». Хотя это наиболее интересно как обобщение функций, сам экземпляр Arrow (->) уже весьма полезен. Например, следующая функция:
spaceAround :: Double -> [Double] -> Double
spaceAround x ys = minimum greater - maximum smaller
where (greater, smaller) = partition (>x) ys
также могут быть записаны с помощью комбинаторов стрелок:
spaceAround x = partition (>x) >>> minimum *** maximum >>> uncurry (-)
Этот вид композиции лучше всего визуализировать с помощью диаграммы:
──── minimum ────
╱ * ╲
──── partition (>x) >>> * >>> uncurry (-) ───
╲ * ╱
──── maximum ────
Вот,
Оператор
>>>- это просто перевернутая версия обычного.(существует также версия<<<которая составляет справа налево). Он передает данные с одного этапа обработки на другой.исходящий
╱╲указывает, что поток данных разделен на два «канала». В терминах типов Haskell это реализуется с помощью кортежей:partition (>x) :: [Double] -> ([Double], [Double])разделяет поток по двум
[Double]каналам, тогда какuncurry (-) :: (Double,Double) -> Doubleобъединяет два
Doubleканала.***является оператором параллельной композиции †. Он позволяетmaximumиminimumработать независимо на разных каналах данных. Для функций сигнатура этого оператора равна(***) :: (b->c) -> (β->γ) -> (b,β)->(c,γ)
† По крайней мере, в категории Hask (т. Е. В экземпляре Arrow (->) ) f***g фактически не вычисляет f и g параллельно, как в, на разных потоках. Теоретически это было бы возможно.