Поиск…


Функциональные композиции с несколькими каналами

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



Modified text is an extract of the original Stack Overflow Documentation
Лицензировано согласно CC BY-SA 3.0
Не связан с Stack Overflow