# Anatomy of Maybe — Part II — Functor

Understanding Functional Programming Thru Optionality

`map` is a pretty cool guy—he’s even pretty regular in normal codebases now. As we come to see data more as a transformation, the idea of mapping just makes sense. Surprisingly many folks think map is just for collections. Really, map is for transforming values inside contexts. You’ve probably used to map in this form:

``````[ 0, 1, 2, 3, 4 ].map((x) => x + 10)
//=> [10, 11, 12, 13, 14]

R.map(R.add(10), [ 0, 1, 2, 3, 4 ])
//=> [10, 11, 12, 13, 14]``````

but that same concept can be applied to `Maybe`. In the previous blog, we talked about how to get values out of a Maybe, but we really need to be able to do things inside the Maybe so that we can hold on to this optionality.

## Functor ≠ Iterable

As we will look at in this and some `Maybe` examples, we can map something that’s not iterable. If we imagined the hand holding a value, or an apple

we have an eat function: `eat : FreshFood → EatenFood`. We know that outside that context we can eat food freely (imagine a floating apple in space). However, we have a context, our hand, with which we must deal with. We can lift that concept of `eat` into hand context with `map`.

``````-- conceptually this is just like a Maybe
type Hand a = Holding a | Empty

Hand.map eat (Holding Apple)
--=> Holding EatenApple``````

and BAM, we have an apple that’s eaten that is still in that hand context!

Had my hand been empty, I would having nothing to eat, so the hand would remain empty. So when you think of `x` is “mappable”, you can start thinking `x` is a Functor. Also with a type system, we can guarantee that we will turn type `a` into type `b`.

Click to expand if you really care to see the full implementation, but it’s basically the next section (but it does compile :3)
``````import Html exposing (Html, text)

type Hand a
= Holding a
| Empty

type FreshFood
= Apple

type EatenFood
= EatenApple

map : (a -> b) -> Hand a -> Hand b
map f hand =
case hand of
Holding value ->
Holding (f value)
Empty ->
Empty

eat : FreshFood -> EatenFood
eat (Apple) =
EatenApple

prestineApple : Hand FreshFood
prestineApple =
Holding Apple

main : Html String
main =
text << toString <| map eat prestineApple
--=> Holding EatenApple``````

## Maybe Functor

``````map : (a -> b) -> Maybe a -> Maybe b
map f maybe =
case maybe of
Just value ->
Just (f value)
Nothing ->
Nothing``````

You can see that we will pattern match the `Maybe` that was passed in. If it’s `Just` and contains a value, apply a value to that value and wrap it back up with a `Just`. In the `Nothing` case, there’s nothing to map, so we return `Nothing`. Reiterating, we are going from some generic `a` to generic `b`, so we can change types.

Elm
``````m : Maybe Int
m = Maybe.map ((*) 2) <| Just 4
--=> Just 8

n : Maybe Int
n = Maybe.map ((*) 2) <| Nothing
--=> Nothing

o : Maybe String
o = Maybe.map toString <| Just 10
--=> Just "10"

p : Maybe String
p = Maybe.map toString <| Nothing
--=> Nothing

q : Maybe (List Int)
q = Maybe.map (List.map ((*) 2)) <| Just [ 0, 2, 4 ]
--=> Just [ 0, 4, 8 ]

r : Maybe (List Int)
r = Maybe.map (List.map ((*) 2) <| Nothing
--=> Nothing``````
JavaScript + Ramda Fantasy
``````const m = Maybe.Just(4).map((x) => x * 2)
//=> Object { value: 8 }

const n = Maybe.Nothing().map((x) => x * 2)
//=> Object {  }

const o = Maybe.Just(10).map((x) => x.toString())
//=> Object { value: "10" }

const p = Maybe.Nothing().map((x) => x.toString())
//=> Object {  }

const q = Maybe.Just([0, 2, 4]).map((xs) => xs.map((x) => x * 2))
//=> Object { value: [0, 4, 8] }

const r = Maybe.Nothing().map((xs) => xs.map((x) => x * 2))
//=> Object {  }``````
JavaScript + Ramda + Ramda Fantasy
``````const s = R.map(R.multiply(2), Maybe.Just(4))
//=> Object { value: 8 }

const t = R.map(R.multiply(2), Maybe.Nothing())
//=> Object {  }

const u = R.map(R.toString, Maybe.Just(10))
//=> Object { value: "10" }

const v = R.map(R.toString, Maybe.Nothing())
//=> Object {  }

const w = R.map(R.map(R.multiply(2)), Maybe.Just([0, 2, 4]))
//=> Object { value: [0, 4, 8] }

const x = R.map(R.map(R.multiply(2)), Maybe.Nothing())
//=> Object {  }``````

## Functor Laws

So there are Functor laws to be proven for a type to be a functor.

``````-- Identity
id :: a -> a

-- Functor map
fmap :: Functor f => (a -> b) -> f a -> f b``````
PureScript Signatures
``````-- Identity
identity ∷ ∀ α t. Category α ⇒ α t t

-- Functor map
map ∷ ∀ f α β. Functor f ⇒ (α → β) → f α → f β``````

### Law 1

``fmap id == id``
PureScript
``map identity == identity``

Mapping with identity is the same as identity itself.

Elm
``````Maybe.map identity <| Just "\$\$"
--=> Just "\$\$"

identity <| Just "\$\$"
--=> Just "\$\$"``````
JavaScript
``````//∷ ∀ α. α → α
const identity = (x) => x

Maybe.Just("\$\$").map(identity)
//=> Object { value: "\$\$" }

identity(Maybe.Just("\$\$"))
//=> Object { value: "\$\$" }``````
JavaScript + Ramda + Ramda Fantasy
``````R.map(R.identity, Maybe.Just("\$\$"))
//=> Object { value: "\$\$" }

R.identity(Maybe.Just("\$\$"))
//=> Object { value: "\$\$" }``````

### Law 2

``fmap (p . q) == (fmap p) . (fmap q)``
PureScript
``map (p <<< q) == (map p) <<< (map q)``

Mapping and mapping again is the same as mapping once, but composing those inner functions. This law has a positive performance side-effect, since it doesn’t have the cost of unwrapping and rewrapping with the Functor context.

We’re going to take a `Maybe (List Int)`, add 1 to each value, then sum the list.

``````j : Maybe (List Int)
j =
Just [ 0, 1, 2, 3 ]

-- Point-full & pipeless
Maybe.map List.sum (Maybe.map (List.map (\x -> x + 1)) j)
--=> Just 6

-- Same as above but using pipe, |>, and taking advantage of currying
j
|> Maybe.map (List.map ((+) 1))
|> Maybe.map List.sum
--=> Just 6

-- Composed gives the same result + THE PERF WIN
Maybe.map (List.map ((+) 1) >> List.sum) j
--=> Just 6``````
Vanilla JavaScript
``````//∷ Maybe [Number]
const j = Maybe.Just([0, 1, 2, 3])

j
.map((xs) => xs.map((x) => x + 1))
.map((xs) => xs.reduce((acc, x) => acc + x, 0))
//=> Object { value: 6 }

// Composed
j.map((xs) =>
xs
.map((x) => x + 1)
.reduce((acc, x) => acc + x, 0)
)
//=> Object { value: 6 }``````
Ramda
``````// Not piped
//=> Object { value: 6 }

// Point-free & piped
R.pipe(
R.map(R.sum),
)(j)
//=> Object { value: 6 }

// Composed
//=> Object { value: 6 }``````

Of note in JS, you start to see that with more complex transformations, the currying of Ramda becomes waaay more terse and also a lot less noisy with the pointful lamdas (often called "anonymous functions" in JS). With a good function API, you can be both expressive, terse, and easy to read.

## Lists & Arrays

We talked about how iterable doesn’t mean functor. So what does that mean for `List`? If map is transforming values in a context, how would transform the values inside a List? `map` by definition has this `(a → b)` part in its signature. If you have a `List Int` and you are going to `List String`, your map implementation better change all values of that list from an `Int` to a `String`. To do that you’d walk a function across all of the list values. Let’s implement this recursively (note this is not how Elm actually does map in the core, and it’s also not optimal since it’s not tail-call optimized).

``````map : (a -> b) -> List a -> List b
map f xs =
case xs of
[] ->
[]
f head :: map f tail``````

Just like the `Maybe`, this starts with a pattern match. Given our empty list, return an empty list, otherwise split on the head and tail of the list, then run the function on the head and cons the return of a recursive call to map on the tail—transforming every value in that list. Granted we are going from `List Int` to `List Int`, not showing `(a → b)` (which is okay), but addition is such an easy-to-understand example. So looking at that in slow motion:

``````map ((+) 1) [ 1, 2, 3 ]
--=> [ 2, 3, 4 ]

((+) 1 1) :: map ((+) 1) [ 2, 3 ]
2 :: map ((+) 1) [ 2, 3 ]
2 :: ((+) 1 2) :: map ((+) 1) [ 3 ]
2 :: 3 :: map ((+) 1) [ 3 ]
2 :: 3 :: ((+) 1 3) :: map ((+) 1) []
2 :: 3 :: 4 :: map ((+) 1) []
2 :: 3 :: 4 :: []
-- Which is already the same as [ 2, 3, 4 ] since
-- that is the underlying structure of a cons list
2 :: 3 :: [ 4 ]
2 :: [ 3, 4 ]
[ 2, 3, 4 ]``````
JavaScript Via Destructuring (Also Not Optimized)
``````//∷ ∀ α β. (α → β) → [α] → [β]
const map = (f, [ head, ...tail ]) =>
head === void 0 ? [] : [ f(head), ...map(f, tail) ]

map((x) => x + 1, [ 1, 2, 3 ])
//=> [ 2, 3, 4 ]

[ 1 + 1, ...map((x) => x + 1, [ 2, 3 ]) ]
[ 2, ...map((x) => x + 1, [ 2, 3 ]) ]
[ 2, ...[ 2 + 1, ...map((x) => x + 1, [ 3 ]) ] ]
[ 2, ...[ 3, ...map((x) => x + 1, [ 3 ]) ] ]
[ 2, ...[ 3, ...[ 3 + 1, ...map((x) => x + 1, []) ] ] ]
[ 2, ...[ 3, ...[ 4, ...map((x) => x + 1, []) ] ] ]
[ 2, ...[ 3, ...[ 4, ...[] ] ] ]
[ 2, ...[ 3, ...[ 4 ] ] ]
[ 2, ...[ 3, 4 ] ]
[ 2, 3, 4 ]``````

The JavaScript map’s signature is a bit misleading, since outside the special typed arrays we can never guarantee in JavaScript array items are of the same type. An error will also be thrown if the argument for the array is not iterable.

## Why Can’t I map a Set?

I get it: transforming values within a context! But with `Set`, why not? I mean it’s iterable and list-like… Well, by definition `Set` includes that fun property of uniqueness. Imagine if we could:

``````//∷ [ℤ]
ints = [ 1, 2, 3, 4 ]

// is it odd?
ints.map((x) => x % 2)
//=> [ 1, 0, 1, 0 ]

// Now imagine that if Set had map
(new Set(ints)).map((x) => x % 2)
//=> ???``````

`Set [ 1, 0, 1, 0 ]` isn’t a `Set` since the values are not unique and `Set [ 0, 1 ]` makes sense-ish, but if we compare that to our above array map implementation, we can’t transform each value and maintain the same size. Losing values isn’t a part of `map`. As such, since we cannot guarantee uniqueness with `map` on `Set`s, `Set` is not a Functor. This should further drive home the functor-is-not-iterable point.

 Note In reality some implementations allow `Set` to be mapped since it’s useful, but one should still be careful

## A Real World Use of Functors

Let’s say we have some (JSON parsed) data

``````{
"characters": [
{
"name": "Ganonu",
"piece": 0
},
{
"name": "Zeldu",
"piece": 1
},
{
"piece": 2
},
{
"name": "Impu",
"piece": -1
},
{
"name": "Midnu",
"piece": -1
},
{
"name": "Tinglu",
"piece": -1
}
]
}``````

This data of a ‘random’ characters, that may or may not have a piece of this thing called the Triforks which can be represented as a tagged union (also known as an enum in some languages). Since JSON can’t represent this structure, our API has returned us an integer representation. Since some characters don’t have a piece, the value needs to be a `Maybe TriforksPiece`. What we want to do is represent this in some virtual DOM (VDOM). If the piece exists, add it to the text of a list item, `<li>`, (i.e. “Zeldu - Wisdom” & “Tinglu”).

So the `map`s we’ll be using:

• Decode.map (Elm only): `Int → TriforksPiece`
• List.map: `Charcter → ( String, Html String )`
• Maybe.map: `TriforksPiece → String`

And a bimap (essentially passing in two function to be about to map both the error and the success) with default to allow a value to fall out

``Result.unpack : (a -> b) -> (e -> b) -> Result a e -> b``
• Result.unpack (Either.either in Ramda Fantasy JS): `String → Html String` + `List Character → Html String`
Elm
``````import Html exposing (Html, li, text)
import Html.Keyed exposing (ul)
import Json.Decode as Decode exposing (Decoder)
import Result.Extra as Result

-- Syntax for building unions and ADTs…
type TriforksPiece
= Power
| Wisdom
| Courage

-- For transforming our JSON’s enum representation
triforksPieceFromEnum : Int -> Maybe TriforksPiece
case i of
0 -> Just Power
1 -> Just Wisdom
2 -> Just Courage
_ -> Nothing

-- For transforming the union back to a String for the view
-- We _could_ run `toString` on Triforks Piece, but this
-- future-proofs us for translations
triforksPieceToString : TriforksPiece -> String
triforksPieceToString tp =
case tp of
Power -> "Power"
Wisdom -> "Wisdom"
Courage -> "Courage"

type alias Character =
{ name : String
, piece : Maybe TriforksPiece
}

-- In Elm we decode and explicitly verify our JSON schema via
-- a Json.Decode.Decoder
-- Note: Decode.map turning our Int into a Maybe TriforksPiece
characterDecoder : Decoder Character
characterDecoder =
Decode.map2 Character
(Decode.field "name" Decode.string)
(Decode.field "piece" Decode.int |> Decode.map triforksPieceFromEnum)

-- Keyed HTML is best used in list-like data like our characters
-- Our label is a good unique key
viewCharacter : Character -> ( String, Html String )
viewCharacter { name, piece } =
let
-- Use map to compose a transformation of a union type
-- into a string & then append to " – ", then let the
-- value fall out with "", then append to the name
label : String
label =
piece
|> Maybe.map (\p -> " - " ++ triforksPieceToString p)
|> Maybe.withDefault ""
|> (++) name
in
-- Ex. <li>Linku - Courage</li> or <li>Impu</li>
( label , li [] [ text label ] )

-- Assume we pass the JSON stringify’d string into the view
-- Unpack an Err’s String into text on failure while
-- putting Ok thru the list maker
view : String -> Html String
view input =
let
charactersDecoder : Decoder (List Character)
charactersDecoder =
Decode.field "characters" (Decode.list characterDecoder)
in
case Decode.decodeString charactersDecoder input of
Ok chars ->
ul [] (List.map viewCharacter chars)
Err err ->
text err``````
JavaScript + Ramda + Ramda Fantasy + virtual-dom
``````import R from "ramda"
import { Either, Maybe } from "ramda-fantasy"
import h from "virtual-dom/h"

// Like Elm’s Dict.get, we need a safe function for getting
// values out of a map, and returning a Maybe since the
// function can fail to retrieve a value. Map.prototype.get
// returns `α | null`.
//∷ ∀ key val. Ord key ⇒ key → Map key val → Maybe val
const mapGet = R.curryN(2, (key, map) =>
map instanceof Map ? Maybe(map.get(key)) : Maybe.Nothing()
)

// Now that we’re done building general helpers…

// Use an `Either` to handle JSON parsing errors — it’s similar
// to a `Maybe`, but is `Either α β = Left α | Right β`.
// We will be validating the structure too.
//∷ String → Either String [Char]
const decodeCharacterJSON = (j) => {
let json

try {
json = JSON.parse(j)
} catch(e) {
// Fail on failed parse
return Either.Left(`JSON parsing fail: \${e.message}`)
}

return R.ifElse(
// condition for characters
R.allPass([
Array.isArray,
R.all(R.propSatisfies((n) => typeof n === "string", "name"))
]),
// is array and all have string name prop, pipe thru & pass
R.pipe(
R.project([ "name", "piece" ]),
Either.Right
),
// else, pipe thru & fail
R.pipe(
JSON.stringify,
R.concat("JSON parsed, but characters are misformed: "),
Either.Left
)
)(R.prop("characters", json))
}

// JavaScript doesn’t support ADTs or Enums, so a Map of
// Strings will have to do.
// Haskell: `newtype TriforksPiece = TriforksPiece String`
// Elm: `type alias TriforksPiece = String`
//∷ Map ℤ TriforksPiece
const TriforksPieces =
new Map([
[ 0, "Power" ],
[ 1, "Wisdom" ],
[ 2, "Courage" ]
])

// Partially apply in the TriforksPiece Map
//∷ ℤ -> Maybe TriforksPiece
R.flip(mapGet)(TriforksPieces)

// Ex. <li>Linku – Courage</li> or <li>Impu</li>
//∷ (Character) → VDOM
viewCharacter = ({ name, piece }) => {
// Remember, piece : Maybe TriforksPiece
//∷ String
const label =
`\${name}\${R.map(R.concat(" – "), piece).getOrElse("")}`

return h("li", { key: label }, label)
}

//∷ [Character] → VDOM
viewCharacters = (chars) =>
h("ul", {}, R.map(viewCharacter, chars))

// Assume our `view` takes in a JSON.stringify’d string of characters
//∷ String → VDOM
const view =
R.pipe(
decodeCharacterJSON,
// map the Either then List to update the Triforks pieces