# Functor: Mappable

## Usage

``````Change a value, `a`,
that's currently stored in some box-like type, `f`,
into `b`
using a function, `(a -> b)`.
``````

## Definition

See its docs: Functor

``````class Functor f where
map :: forall a b. (a -> b) -> f a -> f b

infixl 4 map as <\$>

data Box a = Box a

instance Functor Box where
map :: forall a b. (a -> b) -> Box a ->  Box  b
map                 f         (Box a) =  Box (f a)
``````

Put differently, `Functor` solves a specific problem. If I have a function of type `(a -> b)`, I cannot use that function on values of `a` if they are stored in a box-like type:

``````function :: Int -> String
function 0 = "0"
function _ = "1"

function 5 -- This works!
function (Box 5) -- compiler error! Oh noes!
``````

One could also see `map` as "transforming" a function, so that it also operates on Box-like types. This is often described as "lifting" a function into a Box-like type:

``````map :: forall a b. (a -> b) -> (Box a -> Box b)
map f = (\(Box a) -> Box (f b))
``````

## Laws

### Identity

Definition: `(\x -> x) <\$> fa == fa`

``````-- Start!
(\a -> a) <\$> (Box 4)
-- De-infix "<\$>" to map
map (\a -> a) (Box 4)
-- Replace map's "call signature" with its "body"
Box ((\a -> a) 4)
-- Apply argument by replacing '\a' with its argument '4'
Box ((\4 -> 4)  )
-- Keep only the body of function
Box ((      4)  )
-- Remove parenthesis and whitespace
Box 4
-- Check whether left-hand side (LHS) equals right-hand side (RHS)
(Box 4) == (Box 4)
-- Law met!
true
``````

### Composition

(Remember, `g <<< f` means `(\a -> g (f a))`)

Definition: `map (g <<< f) = (map g) <<< (map f)`

``````-- # Reduce left side of the law #

-- Start!
map ((\y -> y * 10) <<< (\x -> x + 1)) (Box 4)
-- Remember that `f <<< g` means `(\a -> f (g a))`
-- Reduce the "<<<" into one function
map (\x -> 10 * (x + 1)) (Box 4)
-- Replace map's "call signature" with its "body"
Box ((\x -> 10 * (x + 1)) 4)
-- Apply argument by replacing '\x' with its argument '4'
Box ((\4 -> 10 * (4 + 1))  )
-- Keep only the body of function
Box ((      10 * (4 + 1))  )
-- Reduce the body of function to its end result:
Box ((      10 * (5    ))  )
Box ((      10 *  5     )  )
Box ((      50          )  )
-- Remove parenthesis and whitespace
Box 50

-- # Reduce right side of the law #

-- Start!
(map (\y -> y * 10)) <<< (map (\x -> x + 1)) (Box 4)
-- Reduce "<<<" into one function
(\box4    -> map (\y -> y * 10) ( map (\x -> x + 1)  box4  ) ) (Box4)
-- Apply argument
(\(Box 4) -> map (\y -> y * 10) ( map (\x -> x + 1) (Box 4)) )
-- Keep only the body of function
(            map (\y -> y * 10) ( map (\x -> x + 1) (Box 4)) )
-- Replace 2nd map "call signature" with its "body"
(            map (\y -> y * 10) ( Box (\x -> x + 1) 4) )
-- Apply the argument
(            map (\y -> y * 10) ( Box (\4 -> 4 + 1)  ) )
-- Keep only the body of the function
(            map (\y -> y * 10) ( Box (      4 + 1)  ) )
-- Calculate the function
(            map (\y -> y * 10) ( Box (      5    )  ) )
-- Remove unneeded parenthesis
(            map (\y -> y * 10)   Box        5         )
-- Remove unneeded whitespace
(            map (\y -> y * 10) Box 5                  )
-- Replace map's "call signature" with its "body"
(                               Box ((\y -> y * 10) 5) )
-- Apply the argument
(                               Box ((\5 -> 5 * 10)  ) )
-- Keep only the function
(                               Box ((      5 * 10)  ) )
-- Calculate the function
(                               Box ((      50    )  ) )
-- Remove unneeded parenthesis
Box         50
-- Shift everything left
Box 50

-- Test if LHS equals RHS
(Box 50) == (Box 50)
-- Law met!
true
``````

## Derived Functions

See the docs above for their definitions and read through the source code:

• Ignore the `a` value and just replace it with
• the value towards which the arrow points...
• (`voidLeft` / `\$>`): `(Box 4) \$> "a" == (Box "a")`
• (`voidRight` / `<\$`): `"a" <\$ (Box 4) == (Box "a")`
• `Unit` (`void`): `void (Box 4) == (Box unit)`
• Note: `void` is used heavily to make it work with the `Discard` type class in `do` notation.
• Flip the order of map's arguments (`mapFlipped` / `<#>`)
• Generalize `flip`, so that it works for all types (`flap` / `<@>`)