Ответ 1
Как сообщит вам Hackage и/или Hoogle,
(>>>) :: Category k => a`k`b -> b`k`c -> a`k`c
(<<<) :: Category k => b`k`c -> a`k`b -> a`k`c
Заметим, что последнее фактически совпадает с
(.) :: Category k => b`k`c -> a`k`b -> a`k`c
или в форме Prelude
, специализированной для категории функций Hask,
(.) :: (b->c) -> (a->b) -> (a->c)
Итак, <<<
и >>>
просто составляют функции или, в более общем смысле, морфизмы/стрелки.
<<<
состоит в том же направлении, что и знакомый .
, а >>>
переворачивает аргументы так, чтобы "данные текли слева направо".
Теперь, что означает композиция стрелки для категорий, отличных от Hask, зависит, конечно, от категории. Kleisli IO
- это простой пример: скажем, мы имеем чистую функцию
pipe :: Double -> String
pipe = show . sqrt . (+2) . abs
Как я уже сказал, это также можно записать
pipe = abs >>> (+2) >>> sqrt >>> show
Теперь, если вы хотите добавить примитивные записи ввода-вывода (например, на императивном языке), вы можете ввести
type (-|>) = Kleisli IO
abs', add2', sqrt' :: Num a => a -|> a
show' :: Show a => a -|> String
abs' = Kleisli $ \x -> do putStrLn ("Absolute of "++show x++"...")
return $ abs x
add2' = Kleisli $ \x -> do putStrLn ("Add 2 to "++show x++"...")
return $ x + 2
sqrt' = Kleisli $ \x -> do putStrLn ("Square root of "++show x++"...")
return $ sqrt x
show' = Kleisli $ \x -> do putStrLn ("Show "++show x++"...")
return $ show x
С этим вы можете определить
pipe' :: Double -|> String
точно так же, как и раньше, т.е.
pipe' = abs' >>> add2' >>> sqrt' >>> show'
Но теперь вы получите промежуточные результаты, напечатанные как побочный эффект.