Last active
January 20, 2025 09:31
-
-
Save asarkar/00dc069e3b53bbaa964e8da9e5ca0e7b to your computer and use it in GitHub Desktop.
Haskell Arrow Tutorial Code
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
{-# LANGUAGE Arrows #-} | |
module ArrowFun where | |
import Control.Arrow (Arrow, Kleisli (..), (<+>), (>>>)) | |
import qualified Control.Arrow as A | |
import Control.Category (Category) | |
import qualified Control.Category as C | |
import qualified Control.Monad as M | |
import Prelude hiding (liftA2) | |
main :: IO () | |
main = do | |
print hOutput -- 29 | |
print hOutput' -- 29 | |
print h2Output -- [24,8] | |
-- [ "test","!test!","test>","!test>!","<test", | |
-- "!<test!","<test>","!<test>!","foobar", | |
-- "!foobar!","foobar>","!foobar>!","<foobar", | |
-- "!<foobar!","<foobar>","!<foobar>!" | |
-- ] | |
print teaser | |
newtype SimpleFunc a b = SimpleFunc | |
{ runF :: (a -> b) | |
} | |
instance Arrow SimpleFunc where | |
arr f = SimpleFunc f | |
first (SimpleFunc f) = SimpleFunc (mapFst f) | |
where | |
mapFst g (a, b) = (g a, b) | |
second (SimpleFunc f) = SimpleFunc (mapSnd f) | |
where | |
mapSnd g (a, b) = (a, g b) | |
instance Category SimpleFunc where | |
(SimpleFunc g) . (SimpleFunc f) = SimpleFunc (g . f) | |
id = A.arr C.id | |
split :: (Arrow a) => a b (b, b) | |
split = A.arr (\x -> (x, x)) | |
unsplit :: (Arrow a) => (b -> c -> d) -> a (b, c) d | |
unsplit = A.arr . uncurry | |
(***) :: (Arrow a) => a b c1 -> a d c2 -> a (b, d) (c1, c2) | |
f *** g = A.first f >>> A.second g | |
(&&&) :: (Arrow a) => a b c1 -> a b c2 -> a b (c1, c2) | |
f &&& g = split >>> A.first f >>> A.second g | |
liftA2 :: (Arrow a) => (b -> c -> d) -> a e b -> a e c -> a e d | |
liftA2 op f g = split >>> A.first f >>> A.second g >>> unsplit op | |
f :: SimpleFunc Int Int | |
f = A.arr (`div` 2) | |
g :: SimpleFunc Int Int | |
g = A.arr (\x -> x * 3 + 1) | |
h :: SimpleFunc Int Int | |
h = liftA2 (+) f g | |
hOutput :: Int | |
hOutput = runF h 8 | |
h' :: SimpleFunc Int Int | |
h' = proc x -> do | |
fx <- f -< x | |
gx <- g -< x | |
A.returnA -< (fx + gx) | |
hOutput' :: Int | |
hOutput' = runF h' 8 | |
plusminus, double, h2 :: Kleisli [] Int Int | |
plusminus = Kleisli (\x -> [x, -x]) | |
double = A.arr (* 2) | |
h2 = liftA2 (+) plusminus double | |
h2Output :: [Int] | |
h2Output = A.runKleisli h2 8 | |
teaser :: [String] | |
teaser = do | |
let prepend x = A.arr (x ++) | |
append x = A.arr (++ x) | |
withId t = A.returnA <+> t | |
xform = | |
(withId $ prepend "<") | |
>>> (withId $ append ">") | |
>>> (withId $ ((prepend "!") >>> (append "!"))) | |
["test", "foobar"] >>= (A.runKleisli xform) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment