Skip to content

Instantly share code, notes, and snippets.

@Sam-Serpoosh
Last active November 29, 2015 21:06
Show Gist options
  • Save Sam-Serpoosh/4a33af4686f2481312c7 to your computer and use it in GitHub Desktop.
Save Sam-Serpoosh/4a33af4686f2481312c7 to your computer and use it in GitHub Desktop.
This code snippet shows a very powerful concept provided by Haskell's type system.
twice :: Int -> Int
twice = (*2)
twicePossibleNums :: Maybe [Int] -> Maybe [Int]
twicePossibleNums = (fmap . fmap) twice
main :: IO ()
main = putStrLn $ show $ twicePossibleNums (Just [1, 2, 3]) -- => Just [2, 4, 6]
-- How it Works?
-- Maybe & List are Functors in Haskell:
-- class Functor f where
-- fmap :: (a -> b) -> f a -> f b
-- So in the case of Maybe and List `fmap` has the signature:
-- Maybe => fmap :: (a -> b) -> Maybe a -> Maybe b
-- List => fmap :: (a -> b) -> [a] -> [b]
-- Combining/Composing those two Functors will have:
-- Maybe [] => fmap :: (a -> b) -> Maybe [a] -> Maybe [b]
-- The outter Functor is Maybe and the inner one is List.
-- So we can leverage currying of List Functor's `fmap` with
-- our `twice` function to provide appropriately typed function
-- which can be used as the first argument* to Maybe Fucntors'
-- `fmap`:
-- (fmap twice) :: [Int] -> [Int] -- List Functor's `fmap`
-- fmap (fmap twice) :: Maybe [Int] -> Maybe [Int] -- Maybe Functor's `fmap`
-- So we have:
-- twicePossibleNums :: Maybe [Int] -> Maybe [Int]
-- twicePossibleNums = fmap (fmap twice)
-- Or:
-- twicePossibleNums = (fmap . fmap) twice
@Sam-Serpoosh
Copy link
Author

This gives you the ability of composing different single-responsible units/types/typeclasses and handle more complicated situations with nested types etc. This is provided out of the box in Haskell and for many different concepts and not just Functor.

I can't help but thinking that these abstractions and concepts working very smoothly like this at different levels in Haskell, has a lot to do with the fact that they are inspired by Category Theory. Because it has the symphony of consistent abstractions/concepts working at different levels (categories, objects, morphisms, functors, category of "small" categories a.k.a Cat, etc.) in its DNA 😄

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment