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
параллельно, как в, на разных потоках. Теоретически это было бы возможно.