Да, стрелки почти наверняка ваш мужчина.
Я подозреваю, что вы довольно плохо знакомы с Haskell, просто исходя из того, что вы говорите в своем вопросе. Стрелки, вероятно, будут казаться довольно абстрактными, особенно если вы ищете "рамки". Я знаю, что мне потребовалось некоторое время, чтобы действительно понять, что происходит со стрелками.
Так что вы можете посмотреть на эту страницу и сказать: «Да, это похоже на то, что я хочу», а затем довольно заблудиться в том, как начать использовать стрелки для решения проблемы. Вот небольшое руководство, чтобы вы знали, на что смотрите.
Стрелки не решат вашу проблему. Вместо этого они дают вам язык, на котором вы можете сформулировать свою проблему. Вы можете обнаружить, что некоторая предопределенная стрелка будет делать эту работу - возможно, некоторая стрелка Клейсли - но в конце дня вы захотите реализовать стрелку (предопределенные просто дают вам простые способы реализовать их), который выражает то, что вы подразумеваете под «процессором данных». В качестве почти тривиального примера предположим, что вы хотите реализовать свои процессоры данных с помощью простых функций. Вы бы написали:
newtype Proc a b = Proc { unProc :: a -> b }
-- I believe Arrow has recently become a subclass of Category, so assuming that.
instance Category Proc where
id = Proc (\x -> x)
Proc f . Proc g = Proc (\x -> f (g x))
instance Arrow Proc where
arr f = Proc f
first (Proc f) = Proc (\(x,y) -> (f x, y))
Это дает вам механизм для использования различных комбинаций стрелок (***)
, (&&&)
, (>>>)
и т. Д., А также обозначения стрелок, что очень удобно, если вы делаете сложные вещи. Итак, как отмечает Даниэль Фишер в комментарии, конвейер, который вы описали в своем вопросе, может быть составлен следующим образом:
reader >>> partition >>> (handler1 *** handler2) >>> writer
Но крутая вещь в том, что вам решать, что вы подразумеваете под процессором. Возможно реализовать то, что вы упомянули о том, что каждый процессор разветвляет поток аналогичным образом, используя другой тип процессора:
newtype Proc' a b = Proc (Source a -> Sink b -> IO ())
А затем соответствующим образом реализовать комбинаторы.
Так вот, на что вы смотрите: словарь для разговора о создании процессов, который содержит немного кода для повторного использования, но в первую очередь поможет вам мыслить при реализации этих комбинаторов для определения полезного определения процессора в вашем домене.
Один из моих первых нетривиальных проектов на Haskell состоял в том, чтобы реализовать стрелку для квантовой запутанности ; этот проект заставил меня по-настоящему понять образ мышления Хаскелла, что стало переломным моментом в моей карьере программиста. Может быть, этот ваш проект сделает для вас то же самое? : -)