Created
May 14, 2019 09:26
-
-
Save qoelet/c0206d27ffaa4d592c7e62b4edb2bd38 to your computer and use it in GitHub Desktop.
Playing with arrows
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
module Arrows where | |
import Control.Arrow | |
import System.Directory (doesDirectoryExist) | |
-- `arr` lifts a function to an arrow | |
-- arr :: (b -> c) -> a b c | |
-- e.g. pure function (+ 2) :: Integer -> Integer | |
-- b :: Integer | |
-- c :: Integer | |
foo :: Arrow a => a Integer Integer | |
foo = arr (+ 2) | |
bar :: Arrow a => a Integer String | |
bar = arr show | |
-- e.g. monadic function putStrLn :: String -> IO () | |
baz :: Kleisli IO String () | |
baz = Kleisli putStrLn | |
-- e.g. composing these arrows | |
qux :: Kleisli IO Integer () | |
qux = foo >>> bar >>> baz | |
quux :: Kleisli IO () () | |
quux = Kleisli (\_ -> putStrLn "huhu") | |
-- Arrows make the dependence on input explicit | |
-- An arrow type of a b c is the application of | |
-- the parametrised type a to the two parameters | |
-- b and c | |
-- | |
-- `return`, with type a -> m a, converts a value | |
-- into a computation while its analogue for arrows | |
-- `arr`, with type (b -> c) -> a b c, converts | |
-- a function from input to output into a computation | |
-- | |
-- The analogue of `>>=` is just composition of | |
-- arrows | |
-- | |
-- For any monad m, functions of type a -> m b are | |
-- potential arrows we name Kleisli | |
-- | |
-- Arrows generalise monads; | |
-- for every monad type, there is a corresponding | |
-- arrow type | |
-- More sequencing actions | |
-- *Arrows> runKleisli (first foo) (4, 5) | |
-- (6,5) | |
-- *Arrows> runKleisli (second foo) (4, 5) | |
-- (4,7) | |
faux :: Arrow a => a (Integer, Integer) (Integer, Integer) | |
faux = foo *** foo | |
pas :: Arrow a => a Integer (Integer, Integer) | |
pas = foo &&& foo | |
-- An example of a program expressed via monads | |
mProgram :: IO String | |
mProgram | |
= doesDirectoryExist "/foo/bar" | |
>>= (\r -> if r then putStrLn "yes" else putStrLn "no") | |
>> return "huhu" | |
-- Above rewritten via arrows | |
aProgram :: IO String | |
aProgram | |
= runKleisli (Kleisli doesDirectoryExist | |
>>> (arr $ \r -> if r then "yes" else "no") | |
>>> Kleisli putStrLn | |
>>> (Kleisli $ \_ -> return "huhu")) "/foo/bar" | |
main :: IO () | |
main = do | |
(runKleisli (foo >>> bar >>> baz)) 4 | |
(runKleisli (qux >>> quux)) 4 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment