Last active
August 29, 2015 14:04
-
-
Save laser/e2a26007537c6227a95d to your computer and use it in GitHub Desktop.
Bro, do you even liftA2?
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 Main where | |
import Control.Applicative | |
-- represents our API - its constructor takes two functions | |
-- | |
data API = API { apiDouble :: Integer -> Integer, apiTriple :: Integer -> Integer } | |
-- run a pure function as a computation in the IO monad. | |
-- note that the function won't be run until you bind the | |
-- monad. the good news is that the IO monad instantiates | |
-- Functor and Applicative, which let us use <$> and <*> | |
-- | |
taint :: a -> IO a | |
taint f = do | |
putStrLn "thou hast been tainted by IO!" | |
return $ f | |
-- the Functor instance provided by IO: | |
-- | |
-- instance Functor IO where | |
-- fmap f action = do | |
-- result <- action | |
-- return (f result) | |
-- the Applicative instance provided by IO: | |
-- | |
-- instance Applicative IO where | |
-- pure = return | |
-- a <*> b = do | |
-- f <- a | |
-- x <- b | |
-- return (f x) | |
-- some pure functions to expose via the API type | |
-- | |
dbl :: Integer -> Integer | |
dbl x = x * 2 | |
trpl :: Integer -> Integer | |
trpl x = x * 3 | |
-- take a constructor function t: (Integer -> Integer) -> (Integer -> Integer) -> b | |
-- a functor of type F holding a function that goes from (Integer -> Integer) | |
-- and a second functor of type F that goes from (Integer -> Integer) | |
-- and combine these to return a functor of type F that holds a value resulting | |
-- from running the constructor function t | |
-- | |
makeAPI :: Applicative f => t -> f (Integer -> Integer) -> f (Integer -> Integer) -> f API | |
makeAPI constructor functor1 functor2 = step2 (step1 API functor1) functor2 | |
step1 :: Functor f => (a -> b) -> f a -> f b | |
step1 constructor functor = constructor <$> functor | |
step2 :: Applicative f => f (a -> b) -> f a -> f b | |
step2 step1Result functor = step1Result <*> functor | |
-- demonstrate the equivalency of makeAPI and API <$> f1 <*> f2 | |
-- | |
main :: IO () | |
main = do | |
api <- API <$> taint dbl <*> taint trpl | |
api2 <- makeAPI (API) (taint dbl) (taint trpl) | |
putStrLn $ show $ apiDouble api 5 -- 10 | |
putStrLn $ show $ apiTriple api2 10 -- 30 | |
return () |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment