Skip to content

@markus1189 /gist:6959959
Last active

Embed URL

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
  1. Markus Hauck revised this gist . 1 changed file with 2 additions and 2 deletions.
    View
    4 gistfile1.md
    @@ -410,7 +410,7 @@ Yep! It's just `toListOf`.
    >>> [1,2,3] ^.. items
    [1,2,3]
    -# What else can we do with Traversals? [How do they related to Prisms/Lenses?]
    +# What else can we do with Traversals? [How do they relate to Prisms/Lenses?]
    We can get just the first target.
    @@ -578,4 +578,4 @@ But for now, go get yourself a peanut butter and marmalade sandwich.
    ---
    -With help from penguinland.
    +With help from penguinland.
  2. Markus Hauck revised this gist . No changes.
  3. Markus Hauck revised this gist . No changes.
  4. Markus Hauck revised this gist . No changes.
  5. Markus Hauck revised this gist . No changes.
  6. Markus Hauck revised this gist . No changes.
  7. Markus Hauck revised this gist . 1 changed file with 1 addition and 1 deletion.
    View
    2  gistfile1.md
    @@ -366,7 +366,7 @@ What if we make `Prism'`s that focus on particular branches of `String`?
    >>> preview _ParseFalse "True"
    Nothing
    - >>> review True
    + >>> review _ParseTrue True
    "True"
    This is how printer-parsers can sometimes be valid Prisms.
  8. Markus Hauck revised this gist . 1 changed file with 22 additions and 22 deletions.
    View
    44 gistfile1.md
    @@ -10,11 +10,11 @@ Lenses let you apply some of the power of libraries like `hxt` to all data types
    Eventually, you can use lenses to bring things like record syntax, lookups in lists or maps, pattern matching, `Data.Traversable`, scrap your boilerplate, the `newtype` library, and all kinds of type isomorphisms all together under the same mental model.
    -The end result is a way to efficiently contruct and manipulate "methods of poking around inside things" as simple first-class values.
    +The end result is a way to efficiently construct and manipulate "methods of poking around inside things" as simple first-class values.
    # Okay, what is a Lens?
    -A lens is a first-class reference to a subpart of some data type. For instnace, we have `_1` which is the lens that "focuses on" the first element of a pair. Given a lens there are essentially three things you might want to do
    +A lens is a first-class reference to a subpart of some data type. For instance, we have `_1` which is the lens that "focuses on" the first element of a pair. Given a lens there are essentially three things you might want to do
    1. View the subpart
    2. Modify the whole by changing the subpart
    @@ -77,7 +77,7 @@ Yeah, here are the lens laws again written using actual code. Below, `l` is any
    Don't expect to be able to read the code yet, but here's an example from `lens-aeson` which queries and modifies JSON data.
    - -- Returns all of the major versions of an
    + -- Returns all of the major versions of an
    -- array of JSON objects.
    someString ^.. _JSON -- a parser/printer prism
    . _Array -- another prism
    @@ -118,7 +118,7 @@ I'd show you `_1` but it's not a great example of an understandable type. It use
    {-# LANGUAGE TemplateHaskell #-}
    type Degrees = Double
    - type Latitute = Degrees
    + type Latitude = Degrees
    type Longitude = Degrees
    data Meetup = Meetup { _name :: String, _location :: (Latitude, Longitude) }
    @@ -126,7 +126,7 @@ I'd show you `_1` but it's not a great example of an understandable type. It use
    Let's assume we have lenses `name` and `location` which focus on the slots `_name` and `_location` respectively. The underscores are a convention only, but you see them a lot because the Template Haskell magic going on in `makeLenses` will automatically make `name` and `location` if use underscores like that.
    -The type of these lenses is
    +The type of these lenses is
    >>> :info name
    name :: Lens Meetup Meetup String String
    @@ -154,7 +154,7 @@ Yup, if we've got a `Lens s x` and another lens `Lens x a` we can stick them tog
    la :: Lens s x
    lb :: Lens x a
    -
    +
    la . lb :: Lens s a
    Or, more concretely.
    @@ -164,7 +164,7 @@ Or, more concretely.
    # Lenses compose backwards. Can't we make (.) behave like functions?
    -You're right, we could. We don't for various reasons, but the intution is right. Lenses should combine just like functions. One thing that's important about that is `id` can either pre- or post- compose with any lens without affecting it.
    +You're right, we could. We don't for various reasons, but the intuition is right. Lenses should combine just like functions. One thing that's important about that is `id` can either pre- or post- compose with any lens without affecting it.
    forall $ \lens -> lens . id == lens
    forall $ \lens -> id . lens == lens
    @@ -225,7 +225,7 @@ Sometimes we get new operators by augmenting tried and true operators like `(&&)
    (<>~) :: Monoid m => Lens' s m -> m -> (s -> s)
    lens <>~ m = lens %~ (m <>)
    -## What about (^)? Does that show up anywhere else?
    +## What about (^?) Does that show up anywhere else?
    Yes, but we have to talk about `Prism`s and `Traversal`s first.
    @@ -292,7 +292,7 @@ Whenever we can do that, we can make a lens that focuses just on that subpart.
    That's how prisms are dual to lenses. They select just one branch to go down.
    preview :: Prism' s a -> s -> Maybe a
    -
    +
    Which also lets us "go back up" that one branch.
    review :: Prism' s a -> a -> s
    @@ -327,7 +327,7 @@ Yep, `(^?)` is like `(^.)` for `Prism'`s.
    # Are there any other interesting Prisms? [Printer/Parsers]
    -Here's a simple one. We can deconstruct `[]`s using `Prism'`s.
    +Here's a simple one. We can deconstruct `[]`s using `Prism'`s.
    _Cons :: Prism' [a] (a, [a])
    @@ -338,7 +338,7 @@ Here's a simple one. We can deconstruct `[]`s using `Prism'`s.
    Just (1, [2,3])
    _Nil :: Prism' [a] ()
    -
    +
    >>> preview _Nil []
    Just ()
    @@ -385,7 +385,7 @@ A very simple `Traversal'` traverses all of the items in a list.
    In fact, `Traversal'`s are intimately related to lists since if we have a list we also may have either 1, or 0, or many elements. That's one way to `view` a `Traversal`.
    toListOf items :: [a] -> [a]
    -
    +
    >>> toListOf items [1,2,3]
    [1,2,3]
    @@ -420,8 +420,8 @@ We can get just the first target.
    Or the last target
    lastOf :: Traversal' s a -> Maybe a
    -
    - >>> lastOf items [1,2,3]
    +
    + >>> lastOf items [1,2,3]
    Just 3
    ## Why does it use Maybe?
    @@ -441,7 +441,7 @@ Nope, `preview` just handles access that focuses on either 0 or 1 targets.
    Actually, yes, but you might be in for a surprise.
    >>> view items "hello world"
    -
    +
    <interactive>:56:6:
    No instance for (Data.Monoid.Monoid Char)
    arising from a use of `items'
    @@ -493,7 +493,7 @@ That's not even the best part yet.
    We can compose `Lens`es and `Prism`s and `Traversal`s all together and the types will "just work out". Admittedly at this point all that means is that compositions of Lenses are Lenses, compositions of Prisms are Prisms, and everything else is a Traversal.
    -But there are other things in this subtyping hierachy, like `Iso`s.
    +But there are other things in this subtyping hierarchy, like `Iso`s.
    # What are Isos?
    @@ -523,7 +523,7 @@ They can compose on either end of a lens or a prism and the result is a lens or
    How about between `Maybe` and `Either ()`?
    someIso :: Iso' (Maybe a) (Either () a)
    -
    +
    >>> Just "hi" ^. someIso
    Right "hi"
    @@ -545,23 +545,23 @@ Also kind of boring. [How about between an XML tree treating element names as st
    Element (QName { qnPrefix = Just "foaf"
    , qnLocalPart = "Person"
    - })
    + })
    [ (QName { qnPrefix = Just "foaf"
    , qnLocalPart = "name"
    }
    ,"Ernest")
    - ]
    + ]
    []
    - >>> Element "foaf:Person" [("foaf:name", "Ernest")] [] ^? qualified
    - . attributes
    + >>> Element "foaf:Person" [("foaf:name", "Ernest")] [] ^? qualified
    + . attributes
    . _head . _1 . localPart
    Just "name"
    # What is "from" doing there? [Iso Laws]
    `from` "turns an iso around". Since `Iso`s are equivalences they're symmetric and we can treat them as maps in both directions between types. In fact, the `Iso` laws stated above are just that for any iso, `iso`
    -
    +
    view (iso . from iso) == id
    view (from iso . iso) == id
  9. Markus Hauck renamed this gist . 1 changed file with 0 additions and 0 deletions.
    View
    0  gistfile1.txt → gistfile1.md
    File renamed without changes
  10. Markus Hauck created this gist .
    View
    581 gistfile1.txt
    @@ -0,0 +1,581 @@
    +# What is lens?
    +
    +`lens` is a package which provides the type synonym `Lens` which is one of a few implementations of the concept of lenses, or functional references. `lens` also provides a number of generalizations of lenses including `Prism`s, `Traversal`s, `Iso`s, and `Fold`s.
    +
    +# Why do I care?
    +
    +Lenses and their cousins are a way of declaring how to focus deeply into a complex structure. They form a combinator library with sensible, general behavior for things like composition, failure, multiplicity, transformation, and representation.
    +
    +Lenses let you apply some of the power of libraries like `hxt` to all data types in all programs that you write. As this comparison suggests, the initial steps might be very complicated, but, unlike `hxt`, lenses are ubiquitous enough to make learning the complexity pay off over time.
    +
    +Eventually, you can use lenses to bring things like record syntax, lookups in lists or maps, pattern matching, `Data.Traversable`, scrap your boilerplate, the `newtype` library, and all kinds of type isomorphisms all together under the same mental model.
    +
    +The end result is a way to efficiently contruct and manipulate "methods of poking around inside things" as simple first-class values.
    +
    +# Okay, what is a Lens?
    +
    +A lens is a first-class reference to a subpart of some data type. For instnace, we have `_1` which is the lens that "focuses on" the first element of a pair. Given a lens there are essentially three things you might want to do
    +
    +1. View the subpart
    +2. Modify the whole by changing the subpart
    +3. Combine this lens with another lens to look even deeper
    +
    +The first and the second give rise to the idea that lenses are getters and setters like you might have on an object. This intuition is often morally correct and it helps to explain the lens laws.
    +
    +# The lens laws?
    +
    +Yep. Like the monad laws, these are expectations you should have about lenses. Lenses that violate them are *weird*. Here they are
    +
    +1. Get-Put: If you modify something by changing its subpart to exactly what it was before... then nothing happens
    +2. Put-Get: If you modify something by inserting a particular subpart and then viewing the result... you'll get back exactly that subpart
    +3. Put-Put: If you modify something by inserting a particular subpart `a`, and then modify it again inserting a different subpart `b`... it's exactly as if you only did the second step.
    +
    +Lenses that follow these laws are called "very well-behaved".
    +
    +# What does it look like to use a lens?
    +
    +Well, let's look at `_1` again, the lens focusing on the first part of a tuple. We view the first part of the tuple using `view`
    +
    + >>> view _1 ("goal", "chaff")
    + "goal"
    +
    + >>> forall $ \tuple -> view _1 tuple == fst tuple
    + True
    +
    +We modify `_1`'s focused subpart by using `over` (mnemonic: we're mapping our modification "over" the focal point of `_1`).
    +
    + >>> over _1 (++ "!!!") ("goal", "the crowd goes wild")
    + ("goal!!!", "the crowd goes wild")
    +
    + >>> forall $ \tuple -> over _1 f tuple == (\(fst, snd) -> (f fst, snd)) tuple
    + True
    +
    +As a special case of modification, we can set the subpart to be a new subpart. This is called `set`
    +
    + >>> set _1 "set" ("game", "match")
    + ("set", "match")
    +
    + >>> forall $ \tuple -> set _1 x tuple = over _1 (const x) tuple
    + True
    +
    +## Any more examples?
    +
    +Yeah, here are the lens laws again written using actual code. Below, `l` is any "very well-behaved" lens.
    +
    + -- Get-Put
    + >>> forall $ \whole -> set l (view l whole) whole == whole
    + True
    +
    + -- Put-Get
    + >>> forall $ \whole part -> view l (set l part whole) == part
    + True
    +
    + -- Put-Put
    + >>> forall $ \whole part1 part2 -> set l part2 (set l part1) whole = set l part2 whole
    +
    +# What are some large scale, practical examples of lens?
    +
    +Don't expect to be able to read the code yet, but here's an example from `lens-aeson` which queries and modifies JSON data.
    +
    + -- Returns all of the major versions of an
    + -- array of JSON objects.
    + someString ^.. _JSON -- a parser/printer prism
    + . _Array -- another prism
    + . traverse -- a traversal (using Data.Traversable on Aeson's Vector)
    + . _Object -- another another prism
    + . ix "version" -- a traversal across a "map-like thing"
    + . _1 -- a lens into a tuple (major, minor, patch)
    +
    + -- Increments all of the versions above
    + someString & _JSON
    + . _Array
    + . traverse
    + . _Object
    + . ix "version"
    + . _1
    + %~ succ -- apply a function to our deeply focused lens
    +
    + -- We can factor out the lens
    + allVersions :: Traversal' ByteString Int
    + allVersions = _JSON . _Array . traverse . _Object . ix "version" . _1
    +
    + -- and then rewrite the two examples quickly
    +
    + someString ^.. allVersions
    + someString & allVersions %~ succ
    +
    +
    + -- Because lenses, prisms, traversals, are all first class in Haskell!
    +
    +# Wait a second, GHCi is telling me the types of these things are absurd!
    +
    +Yeah, sorry about that. "It'll make sense eventually", but the types start out tricky.
    +
    +Try to look at the type synonyms only. We can use `:info` to make sure that GHCi tells us the type synonym instead of the really funky fully expanded types.
    +
    +I'd show you `_1` but it's not a great example of an understandable type. It uses some weird extra machinery. Instead, how about an example.
    +
    + {-# LANGUAGE TemplateHaskell #-}
    +
    + type Degrees = Double
    + type Latitute = Degrees
    + type Longitude = Degrees
    +
    + data Meetup = Meetup { _name :: String, _location :: (Latitude, Longitude) }
    + makeLenses ''Meetup
    +
    +Let's assume we have lenses `name` and `location` which focus on the slots `_name` and `_location` respectively. The underscores are a convention only, but you see them a lot because the Template Haskell magic going on in `makeLenses` will automatically make `name` and `location` if use underscores like that.
    +
    +The type of these lenses is
    +
    + >>> :info name
    + name :: Lens Meetup Meetup String String
    +
    + >>> :info location
    + age :: Lens Meetup Meetup (Latitude, Longitude) (Latitude, Longitude)
    +
    + >>> :type location
    + age :: Functor f => ((Latitude, Longitude) -> f (Latitude, Longitude)) -> (Meetup -> f Meetup)
    +
    + -- whoops! Ignore that for now please
    +
    +# Four type parameters? Isn't that a bit much?
    +
    +You're right, we'll use the simplified forms for now. This is highly recommended until you get the hang of things. The simplified types are appended with apostrophes. Now the types of `name` and `location` are
    +
    + name :: Lens' Meetup String
    + age :: Lens' Meetup (Latitude, Longitude)
    +
    +These types tell us that, for instance, the `name` lens focuses *from* a `Meetup` and *to* a `String`. Generally we write `Lens' s a` and throughout the documentation `s` and `t` tend to be where a lens is focusing *from* and `a` or `b` tend to be where the lens is focusing *to*.
    +
    +# Okay, that makes sense. Didn't you say we can compose lenses?
    +
    +Yup, if we've got a `Lens s x` and another lens `Lens x a` we can stick them together to get `Lens s a`. Strangely, we just use regular old `(.)` to do it.
    +
    + la :: Lens s x
    + lb :: Lens x a
    +
    + la . lb :: Lens s a
    +
    +Or, more concretely.
    +
    + meetupLat = location . _1 :: Lens Meetup Latitude
    + meetupLon = location . _2 :: Lens Meetup Longitude
    +
    +# Lenses compose backwards. Can't we make (.) behave like functions?
    +
    +You're right, we could. We don't for various reasons, but the intution is right. Lenses should combine just like functions. One thing that's important about that is `id` can either pre- or post- compose with any lens without affecting it.
    +
    + forall $ \lens -> lens . id == lens
    + forall $ \lens -> id . lens == lens
    +
    +(N.B. If you're categorically inclined, lenses-with-apostrophes would form a `Category` if we did somehow reverse the composition order.)
    +
    +## That's still pretty annoying
    +
    +It's true. On the bright side, lenses often feel a whole lot like OO-style slot access like `Person.name`. The reversed composition thing can be thought of as punning on that.
    +
    + >>> Meetup { ... } ^. location . _1
    + 80.3 :: Latitude
    +
    +# What is that (^.)?
    +
    +Oh, it's just `view` written infix. Here's the Put-Get law again
    +
    + >>> forall $ \lens whole part -> (set lens part whole) ^. lens == part
    + True
    +
    +## Actually there are a whole lot of operators in lens
    +
    +Yup, some people find them convenient.
    +
    +# Actually there are a WHOLE LOT of operators in lens---over 100
    +
    +Very convenient! But that *is* a lot. To make it bearable, there are some tricks for remembering them.
    +
    +1. Operators that begin with `^` are kinds of `view`s. The only example we've seen so far is `(^.)` which is... well, it's just `view` exactly.
    +2. Operators that end with `~` are like `over` or `set`. In fact, `(.~) == set` and `(%~)` is `over`.
    +3. Operators that have `.` in them are usually somehow "basic"
    +4. Operators that have `%` in them usually take functions
    +5. Operators that have `=` in them are just like their cousins where `=` is replaced by `~`, but instead of taking the whole object as an argument, they apply their modifications in a `State` monad.
    +
    +## Is that really worth it?
    +
    +Maybe. Who knows!
    +
    +If you don't like them, then all of the operators have regular named functions as well.
    +
    +## ... Some examples would be nice
    +
    +Ok.
    +
    + (.~) :: Lens' s a -> a -> (s -> s)
    + (.=) :: Lens' s a -> a -> State s ()
    + (%~) :: Lens' s a -> (a -> a) -> (s -> s)
    + (%=) :: Lens' s a -> (a -> a) -> State s ()
    +
    +Sometimes we get new operators by augmenting tried and true operators like `(&&)` with `~` and `=`
    +
    + (&&~) :: Lens' s Bool -> Bool -> (s -> s)
    + (&&=) :: Lens' s Bool -> Bool -> State s ()
    +
    + lens &&~ bool = lens %~ (bool &&)
    + lens &&= bool = lens %= (bool &&)
    +
    + (<>~) :: Monoid m => Lens' s m -> m -> (s -> s)
    + lens <>~ m = lens %~ (m <>)
    +
    +## What about (^)? Does that show up anywhere else?
    +
    +Yes, but we have to talk about `Prism`s and `Traversal`s first.
    +
    +# Okay. What are Prisms?
    +
    +They're like lenses for sum types.
    +
    +## What does that mean?
    +
    +Well, what happens if we try to make lenses for a sum type?
    +
    + -- This doesn't work... or exist
    + _left :: Lens' (Either a b) a
    +
    + >>> view _left (Left ())
    + () -- okay, I buy that
    +
    + >>> view _left (Right ())
    + error! -- oh, there's no subpart there
    +
    +`Prism`s are kind of like `Lens`es that can fail or miss.
    +
    +## So we use Maybe instead, right?
    +
    +We could try that.
    +
    + _left :: Lens' (Either a b) (Maybe a)
    +
    + >>> view _left (Left ())
    + Just ()
    +
    + >>> view _left (Right ())
    + Nothing
    +
    +But it doesn't compose well.
    +
    + _left . name :: Lens (Either Meetup Meetup) ??? -- String? Maybe String?
    +
    +We'd need a `Lens` that looks into `Maybe`:
    +
    + _just :: Lens' (Maybe a) (Maybe a)
    + _just = id
    +
    +Oh. That doesn't get us anywhere. Let's start over.
    +
    +# Okay. What are Prisms? (Take Two)
    +
    +Prisms are the duals of lenses. While lenses pick apart some subpart of a product type like a tuple, prisms go down one branch of a sum type like `Either`... Or else they fail.
    +
    +## Right, a Lens splits out one subpart of a whole. A Prism takes one subbranch.
    +
    +Exactly!
    +
    +Think of a product type as being made of both a subpart and a "whole with a hole in it" where the subpart used to go.
    +
    + product = (a, b)
    + subpart = a
    + whole-with-a-hole = \x -> (x, b)
    +
    +Whenever we can do that, we can make a lens that focuses just on that subpart.
    +
    +## A sum type can be broken into some particular subbranch and all-the-other-ones
    +
    +That's how prisms are dual to lenses. They select just one branch to go down.
    +
    + preview :: Prism' s a -> s -> Maybe a
    +
    +Which also lets us "go back up" that one branch.
    +
    + review :: Prism' s a -> a -> s
    +
    +For instance
    +
    + _Left :: Prism' (Either a b) a
    +
    + >>> preview _Left (Left "hi")
    + Just "hi"
    +
    + >>> preview _Left (Right "hi")
    + Nothing
    +
    + >>> review _Left "hi"
    + Left "hi"
    +
    + _Just :: Prism' (Maybe a) a
    +
    + >>> preview _Just (Just "hi")
    + Just "hi"
    +
    + >>> review _Just "hi"
    + Just "hi"
    +
    + >>> Left "hi" ^? _Left
    + Just "hi"
    +
    +## Oh, there's another (^)-like operator!
    +
    +Yep, `(^?)` is like `(^.)` for `Prism'`s.
    +
    +# Are there any other interesting Prisms? [Printer/Parsers]
    +
    +Here's a simple one. We can deconstruct `[]`s using `Prism'`s.
    +
    + _Cons :: Prism' [a] (a, [a])
    +
    + >>> preview _Cons []
    + Nothing
    +
    + >>> preview _Cons [1,2,3]
    + Just (1, [2,3])
    +
    + _Nil :: Prism' [a] ()
    +
    + >>> preview _Nil []
    + Just ()
    +
    + >>> preview _Nil [1,2,3]
    + Nothing
    +
    +Here's a strange one. `String` is a very strange sum type.
    +
    +## No it isn't. It's just a List again.
    +
    +But `Char` can be thought of as the sum of all characters. And if we "flatten" `Char` into `[]` we can think of `String` as being the "sum of all possible strings"
    +
    + data String = "a" | "b" | "c" | "europe" | "curry" | "dosa" | "applejacks" ...
    +
    +## Okay, sure. Is that important?
    +
    +What if we make `Prism'`s that focus on particular branches of `String`?
    +
    + _ParseTrue :: Prism' String Bool
    + _ParseFalse :: Prism' String Bool
    +
    + >>> preview _ParseTrue "True"
    + Just True
    +
    + >>> preview _ParseFalse "True"
    + Nothing
    +
    + >>> review True
    + "True"
    +
    +This is how printer-parsers can sometimes be valid Prisms.
    +
    +# I think I understand Prisms now. What are Traversals?
    +
    +Traversals are Lenses which focus on multiple targets simultaneously. We actually don't know how many targets they might be focusing on: it could be exactly 1 (like a Lens) or maybe 0 (like a Prism) or 300.
    +
    +A very simple `Traversal'` traverses all of the items in a list.
    +
    + items :: Traversal' [a] a
    + items = traverse -- from Data.Traversable, actually
    + -- this is our first implementation of anything in `lens`
    + -- but don't worry about it right now
    +
    +In fact, `Traversal'`s are intimately related to lists since if we have a list we also may have either 1, or 0, or many elements. That's one way to `view` a `Traversal`.
    +
    + toListOf items :: [a] -> [a]
    +
    + >>> toListOf items [1,2,3]
    + [1,2,3]
    +
    +## That's pretty boring.
    +
    +It is. We can define `items` for any `Traversable` though using the exact same definition.
    +
    + items :: Traversable t => Traversal' (t a) a
    + items = traverse
    +
    + flatten :: Tree a -> [a]
    + flatten = toListOf items
    +
    +## That's no big deal, though. It's just another way to use Data.Traversable
    +
    +For now, but `Traversal` will eventually show a close relationship with `Lens` and `Prism`.
    +
    +## Do we have another (^)-like operator for Traversals at least?
    +
    +Yep! It's just `toListOf`.
    +
    + >>> [1,2,3] ^.. items
    + [1,2,3]
    +
    +# What else can we do with Traversals? [How do they related to Prisms/Lenses?]
    +
    +We can get just the first target.
    +
    + firstOf :: Traversal' s a -> Maybe a
    + firstOf items :: Traversable t => t a -> Maybe a
    +
    +Or the last target
    +
    + lastOf :: Traversal' s a -> Maybe a
    +
    + >>> lastOf items [1,2,3]
    + Just 3
    +
    +## Why does it use Maybe?
    +
    +The `Traversal` could have no targets.
    +
    +## Is this like `preview`?
    +
    +Yeah, `firstOf` is `preview`.
    +
    +## But I thought preview was preview---and that it was specialized to Prisms?
    +
    +Nope, `preview` just handles access that focuses on either 0 or 1 targets.
    +
    +## Can I use view on Traversals too?
    +
    +Actually, yes, but you might be in for a surprise.
    +
    + >>> view items "hello world"
    +
    + <interactive>:56:6:
    + No instance for (Data.Monoid.Monoid Char)
    + arising from a use of `items'
    + Possible fix:
    + add an instance declaration for (Data.Monoid.Monoid Char)
    + In the first argument of `view', namely `items'
    + In the expression: view items "hello world"
    + In an equation for `it': it = view items "hello world"
    +
    +## What is Monoid doing here?
    +
    +It represents the notion of failure. It's just like that `Maybe` we tried to use earlier when investigating `Prism`.
    +
    +## So we can use view if our targets are Monoids?
    +
    +Yep. What do you think `["hello ", "world"] ^. items` gets us?
    +
    +## The Monoid product of the items---"hello world"
    +
    +Exactly! What about `[] ^. items`?
    +
    +## An ambiguous type error!
    +
    +Okay, yes. What about `[] ^. items :: String`?
    +
    +## The empty string, ""
    +
    +And `[] ^. items :: Monoid m => m`?
    +
    +## Whatever mempty is for m
    +
    +Bingo.
    +
    +# So, Traversals generalize Prisms and Lenses somehow?
    +
    +Yeah. It works because `Prism`, `Lens`, and `Traversal` are all just type synonyms---Those scary types that GHCi sometimes prints out actually do line up. That's a big reason why they're left in.
    +
    +# Is this subtyping?
    +
    +Kind of! That's what [the scary chart on the lens Hackage page](http://hackage.haskell.org/package/lens) shows.
    +
    +## But Haskell doesn't have subtyping
    +
    +It's a big clever hack, really. Without it there'd be completely separate combinators for `Lens`, `Prism`, `Traversal`, and all the other things in `lens` that we haven't talked about yet... even though they all end up with identical code at their core.
    +
    +That's not even the best part yet.
    +
    +# What's the best part about the subtyping hack?
    +
    +We can compose `Lens`es and `Prism`s and `Traversal`s all together and the types will "just work out". Admittedly at this point all that means is that compositions of Lenses are Lenses, compositions of Prisms are Prisms, and everything else is a Traversal.
    +
    +But there are other things in this subtyping hierachy, like `Iso`s.
    +
    +# What are Isos?
    +
    +Isos are isomorphisms, connections between types that are equivalent in every way.
    +
    +More concretely, an Iso is a forward mapping and a backward mapping such that the forward mapping inverts the backward mapping and the backward mapping inverts the forward mapping.
    +
    + fw . bw = id
    + bw . fw = id
    +
    +(N.B. This is again exactly a `Category` isomorphism.)
    +
    +## Isos are in the lens subtyping hierarchy?
    +
    +Yep! They are more primitive than either `Lens` or `Prism`.
    +
    +If we think of a `Lens' s a` as a type which splits the product type `s` into its subpart `a` and the context of that subpart, `a -> s`, an `Iso` is a trivial lens where the context is just `id`.
    +
    +If we think of a `Prism' s a` as a type which splits the sum type `s` into a privileged branch and "all the other" branches then an `Iso` is a trivial `Prism` where there's just one branch and we're privileging exactly it.
    +
    +## How do Isos compose with Lenses and Prisms?
    +
    +They can compose on either end of a lens or a prism and the result is a lens or a prism respectively. Isos are "iso" (unchanging) because no matter where you put them in a lens pipeline they leave things as they were.
    +
    +# What are some example Isos?
    +
    +How about between `Maybe` and `Either ()`?
    +
    + someIso :: Iso' (Maybe a) (Either () a)
    +
    + >>> Just "hi" ^. someIso
    + Right "hi"
    +
    +That's a little boring. How about between strict and lazy `ByteString`s?
    +
    + strict :: Iso' Lazy.ByteString Strict.ByteString
    +
    + >>> "foobar" ^. strict
    + "foobar"
    +
    + >>> "foobar" ^. strict . from strict
    + "foobar"
    +
    +Also kind of boring. [How about between an XML tree treating element names as strings and an XML tree treating element names as Qualified Names](http://hackage.haskell.org/package/hexpat-lens-0.0.7/docs/Text-XML-Expat-Lens-Names.html)?
    +
    + qualified :: Iso' (Node String String) (Node (QName String) String)
    +
    + >>> Element "foaf:Person" [("foaf:name", "Ernest")] [] ^. qualified
    +
    + Element (QName { qnPrefix = Just "foaf"
    + , qnLocalPart = "Person"
    + })
    + [ (QName { qnPrefix = Just "foaf"
    + , qnLocalPart = "name"
    + }
    + ,"Ernest")
    + ]
    + []
    +
    + >>> Element "foaf:Person" [("foaf:name", "Ernest")] [] ^? qualified
    + . attributes
    + . _head . _1 . localPart
    + Just "name"
    +
    +# What is "from" doing there? [Iso Laws]
    +
    +`from` "turns an iso around". Since `Iso`s are equivalences they're symmetric and we can treat them as maps in both directions between types. In fact, the `Iso` laws stated above are just that for any iso, `iso`
    +
    + view (iso . from iso) == id
    + view (from iso . iso) == id
    +
    +## That's pretty cool
    +
    +`Iso`s are pretty cool. They're one of my favorite parts of `lens`.
    +
    +
    +# What if I have any more questions?
    +
    +This list may grow over time. Please ask them and leave any comments.
    +
    +But for now, go get yourself a peanut butter and marmalade sandwich.
    +
    +---
    +
    +With help from penguinland.
Something went wrong with that request. Please try again.