2007 lines
50 KiB
Text
2007 lines
50 KiB
Text
{
|
||
"cells": [
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"- Each type of **Optic** comes with a set of compatible **actions**.\n",
|
||
"\n",
|
||
"Lenses have the following concrete gaurantees.\n",
|
||
"\n",
|
||
"* A Lens focuses (i.e selects) a single piece of data within a larger structure.\n",
|
||
"* A Lens must **never fail** to **get** or **modify** that focus.\n",
|
||
"\n",
|
||
"These constraints unlock a few **actions** we can perform on lenses.\n",
|
||
"\n",
|
||
"* We can use a lens to **view** the **focus** within a structure.\n",
|
||
"* We can use a lens to **set** the **focus** within a structure.\n",
|
||
"* We can use a lens to **modify** the **focus** within a structure."
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": 14,
|
||
"metadata": {},
|
||
"outputs": [
|
||
{
|
||
"data": {
|
||
"text/plain": [
|
||
"\"hello\""
|
||
]
|
||
},
|
||
"metadata": {},
|
||
"output_type": "display_data"
|
||
}
|
||
],
|
||
"source": [
|
||
"{-# LANGUAGE TemplateHaskell #-}\n",
|
||
"{-# LANGUAGE FlexibleInstances #-}\n",
|
||
"{-# LANGUAGE FlexibleContexts #-}\n",
|
||
"{-# LANGUAGE RankNTypes #-}\n",
|
||
"{-# LANGUAGE ScopedTypeVariables #-}\n",
|
||
"{-# LANGUAGE TypeApplications #-}\n",
|
||
"{-# LANGUAGE TypeFamilies #-}\n",
|
||
"{-# LANGUAGE InstanceSigs #-}\n",
|
||
"\n",
|
||
"import Control.Lens\n",
|
||
"import Numeric.Lens\n",
|
||
"import Data.Bits.Lens\n",
|
||
"import Data.Data.Lens\n",
|
||
"\n",
|
||
"import Control.Applicative\n",
|
||
"import Data.Char as C\n",
|
||
"import qualified Data.Map as M\n",
|
||
"import qualified Data.Set as S\n",
|
||
"import qualified Data.Text as T\n",
|
||
"import qualified Data.List as L\n",
|
||
"\n",
|
||
"view (_2 . _1) (42, (\"hello\", False))\n",
|
||
"\n",
|
||
"-- view is the action\n",
|
||
"-- (_2 . _1) is the path\n",
|
||
"-- (42, (\"hello\", False)) is the structure\n",
|
||
"-- \"hello\" is the focus"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"## Exercises - Optic Anatomy"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": 16,
|
||
"metadata": {},
|
||
"outputs": [
|
||
{
|
||
"data": {
|
||
"text/plain": [
|
||
"2"
|
||
]
|
||
},
|
||
"metadata": {},
|
||
"output_type": "display_data"
|
||
},
|
||
{
|
||
"data": {
|
||
"text/plain": [
|
||
"(False,Left \"new\")"
|
||
]
|
||
},
|
||
"metadata": {},
|
||
"output_type": "display_data"
|
||
},
|
||
{
|
||
"data": {
|
||
"text/plain": [
|
||
"\"TESTING ONE two three\""
|
||
]
|
||
},
|
||
"metadata": {},
|
||
"output_type": "display_data"
|
||
},
|
||
{
|
||
"data": {
|
||
"text/plain": [
|
||
"\"supercalifragilisticexpialidocious\""
|
||
]
|
||
},
|
||
"metadata": {},
|
||
"output_type": "display_data"
|
||
}
|
||
],
|
||
"source": [
|
||
"view (_1 . _2) ((1, 2), 3)\n",
|
||
"\n",
|
||
"-- view is the action\n",
|
||
"-- (_1 . _2) is the path. Focus on the 1st member of tuple and then the 2nd member of 1st member\n",
|
||
"-- ((1, 2), 3) is the structure\n",
|
||
"-- 2 is the focus\n",
|
||
"\n",
|
||
"set (_2 . _Left) \"new\" (False, Left \"old\")\n",
|
||
"\n",
|
||
"-- set is the action\n",
|
||
"-- (_2 . _Left) is the path\n",
|
||
"-- (False, Left \"Old\") is the structure\n",
|
||
"-- \"old\" is the focus\n",
|
||
"\n",
|
||
"over (taking 2 worded . traversed) C.toUpper \"testing one two three\"\n",
|
||
"\n",
|
||
"-- over is the action\n",
|
||
"-- (taking 2 worded . traversed) is the path\n",
|
||
"-- \"testing one two three\"\n",
|
||
"-- \"testing one\" is the focus\n",
|
||
"\n",
|
||
"foldOf (both . each) ([\"super\", \"cali\"],[\"fragilistic\", \"expialidocious\"])\n",
|
||
"\n",
|
||
"-- foldOf is the action\n",
|
||
"-- (both . each) is the path\n",
|
||
"-- The rest is the structure"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"## Lens Actions\n",
|
||
"\n",
|
||
"### Viewing through lenses"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": 25,
|
||
"metadata": {},
|
||
"outputs": [
|
||
{
|
||
"data": {
|
||
"text/html": [
|
||
"<style>/* Styles used for the Hoogle display in the pager */\n",
|
||
".hoogle-doc {\n",
|
||
"display: block;\n",
|
||
"padding-bottom: 1.3em;\n",
|
||
"padding-left: 0.4em;\n",
|
||
"}\n",
|
||
".hoogle-code {\n",
|
||
"display: block;\n",
|
||
"font-family: monospace;\n",
|
||
"white-space: pre;\n",
|
||
"}\n",
|
||
".hoogle-text {\n",
|
||
"display: block;\n",
|
||
"}\n",
|
||
".hoogle-name {\n",
|
||
"color: green;\n",
|
||
"font-weight: bold;\n",
|
||
"}\n",
|
||
".hoogle-head {\n",
|
||
"font-weight: bold;\n",
|
||
"}\n",
|
||
".hoogle-sub {\n",
|
||
"display: block;\n",
|
||
"margin-left: 0.4em;\n",
|
||
"}\n",
|
||
".hoogle-package {\n",
|
||
"font-weight: bold;\n",
|
||
"font-style: italic;\n",
|
||
"}\n",
|
||
".hoogle-module {\n",
|
||
"font-weight: bold;\n",
|
||
"}\n",
|
||
".hoogle-class {\n",
|
||
"font-weight: bold;\n",
|
||
"}\n",
|
||
".get-type {\n",
|
||
"color: green;\n",
|
||
"font-weight: bold;\n",
|
||
"font-family: monospace;\n",
|
||
"display: block;\n",
|
||
"white-space: pre-wrap;\n",
|
||
"}\n",
|
||
".show-type {\n",
|
||
"color: green;\n",
|
||
"font-weight: bold;\n",
|
||
"font-family: monospace;\n",
|
||
"margin-left: 1em;\n",
|
||
"}\n",
|
||
".mono {\n",
|
||
"font-family: monospace;\n",
|
||
"display: block;\n",
|
||
"}\n",
|
||
".err-msg {\n",
|
||
"color: red;\n",
|
||
"font-style: italic;\n",
|
||
"font-family: monospace;\n",
|
||
"white-space: pre;\n",
|
||
"display: block;\n",
|
||
"}\n",
|
||
"#unshowable {\n",
|
||
"color: red;\n",
|
||
"font-weight: bold;\n",
|
||
"}\n",
|
||
".err-msg.in.collapse {\n",
|
||
"padding-top: 0.7em;\n",
|
||
"}\n",
|
||
".highlight-code {\n",
|
||
"white-space: pre;\n",
|
||
"font-family: monospace;\n",
|
||
"}\n",
|
||
".suggestion-warning { \n",
|
||
"font-weight: bold;\n",
|
||
"color: rgb(200, 130, 0);\n",
|
||
"}\n",
|
||
".suggestion-error { \n",
|
||
"font-weight: bold;\n",
|
||
"color: red;\n",
|
||
"}\n",
|
||
".suggestion-name {\n",
|
||
"font-weight: bold;\n",
|
||
"}\n",
|
||
"</style><span class='get-type'>_1 :: forall s t a b (f :: * -> *). (Field1 s t a b, Functor f) => (a -> f b) -> s -> f t</span>"
|
||
],
|
||
"text/plain": [
|
||
"_1 :: forall s t a b (f :: * -> *). (Field1 s t a b, Functor f) => (a -> f b) -> s -> f t"
|
||
]
|
||
},
|
||
"metadata": {},
|
||
"output_type": "display_data"
|
||
},
|
||
{
|
||
"data": {
|
||
"text/html": [
|
||
"<style>/* Styles used for the Hoogle display in the pager */\n",
|
||
".hoogle-doc {\n",
|
||
"display: block;\n",
|
||
"padding-bottom: 1.3em;\n",
|
||
"padding-left: 0.4em;\n",
|
||
"}\n",
|
||
".hoogle-code {\n",
|
||
"display: block;\n",
|
||
"font-family: monospace;\n",
|
||
"white-space: pre;\n",
|
||
"}\n",
|
||
".hoogle-text {\n",
|
||
"display: block;\n",
|
||
"}\n",
|
||
".hoogle-name {\n",
|
||
"color: green;\n",
|
||
"font-weight: bold;\n",
|
||
"}\n",
|
||
".hoogle-head {\n",
|
||
"font-weight: bold;\n",
|
||
"}\n",
|
||
".hoogle-sub {\n",
|
||
"display: block;\n",
|
||
"margin-left: 0.4em;\n",
|
||
"}\n",
|
||
".hoogle-package {\n",
|
||
"font-weight: bold;\n",
|
||
"font-style: italic;\n",
|
||
"}\n",
|
||
".hoogle-module {\n",
|
||
"font-weight: bold;\n",
|
||
"}\n",
|
||
".hoogle-class {\n",
|
||
"font-weight: bold;\n",
|
||
"}\n",
|
||
".get-type {\n",
|
||
"color: green;\n",
|
||
"font-weight: bold;\n",
|
||
"font-family: monospace;\n",
|
||
"display: block;\n",
|
||
"white-space: pre-wrap;\n",
|
||
"}\n",
|
||
".show-type {\n",
|
||
"color: green;\n",
|
||
"font-weight: bold;\n",
|
||
"font-family: monospace;\n",
|
||
"margin-left: 1em;\n",
|
||
"}\n",
|
||
".mono {\n",
|
||
"font-family: monospace;\n",
|
||
"display: block;\n",
|
||
"}\n",
|
||
".err-msg {\n",
|
||
"color: red;\n",
|
||
"font-style: italic;\n",
|
||
"font-family: monospace;\n",
|
||
"white-space: pre;\n",
|
||
"display: block;\n",
|
||
"}\n",
|
||
"#unshowable {\n",
|
||
"color: red;\n",
|
||
"font-weight: bold;\n",
|
||
"}\n",
|
||
".err-msg.in.collapse {\n",
|
||
"padding-top: 0.7em;\n",
|
||
"}\n",
|
||
".highlight-code {\n",
|
||
"white-space: pre;\n",
|
||
"font-family: monospace;\n",
|
||
"}\n",
|
||
".suggestion-warning { \n",
|
||
"font-weight: bold;\n",
|
||
"color: rgb(200, 130, 0);\n",
|
||
"}\n",
|
||
".suggestion-error { \n",
|
||
"font-weight: bold;\n",
|
||
"color: red;\n",
|
||
"}\n",
|
||
".suggestion-name {\n",
|
||
"font-weight: bold;\n",
|
||
"}\n",
|
||
"</style><span class='get-type'>Lens' :: * -> * -> *</span>"
|
||
],
|
||
"text/plain": [
|
||
"Lens' :: * -> * -> *"
|
||
]
|
||
},
|
||
"metadata": {},
|
||
"output_type": "display_data"
|
||
},
|
||
{
|
||
"data": {
|
||
"text/html": [
|
||
"<style>/* Styles used for the Hoogle display in the pager */\n",
|
||
".hoogle-doc {\n",
|
||
"display: block;\n",
|
||
"padding-bottom: 1.3em;\n",
|
||
"padding-left: 0.4em;\n",
|
||
"}\n",
|
||
".hoogle-code {\n",
|
||
"display: block;\n",
|
||
"font-family: monospace;\n",
|
||
"white-space: pre;\n",
|
||
"}\n",
|
||
".hoogle-text {\n",
|
||
"display: block;\n",
|
||
"}\n",
|
||
".hoogle-name {\n",
|
||
"color: green;\n",
|
||
"font-weight: bold;\n",
|
||
"}\n",
|
||
".hoogle-head {\n",
|
||
"font-weight: bold;\n",
|
||
"}\n",
|
||
".hoogle-sub {\n",
|
||
"display: block;\n",
|
||
"margin-left: 0.4em;\n",
|
||
"}\n",
|
||
".hoogle-package {\n",
|
||
"font-weight: bold;\n",
|
||
"font-style: italic;\n",
|
||
"}\n",
|
||
".hoogle-module {\n",
|
||
"font-weight: bold;\n",
|
||
"}\n",
|
||
".hoogle-class {\n",
|
||
"font-weight: bold;\n",
|
||
"}\n",
|
||
".get-type {\n",
|
||
"color: green;\n",
|
||
"font-weight: bold;\n",
|
||
"font-family: monospace;\n",
|
||
"display: block;\n",
|
||
"white-space: pre-wrap;\n",
|
||
"}\n",
|
||
".show-type {\n",
|
||
"color: green;\n",
|
||
"font-weight: bold;\n",
|
||
"font-family: monospace;\n",
|
||
"margin-left: 1em;\n",
|
||
"}\n",
|
||
".mono {\n",
|
||
"font-family: monospace;\n",
|
||
"display: block;\n",
|
||
"}\n",
|
||
".err-msg {\n",
|
||
"color: red;\n",
|
||
"font-style: italic;\n",
|
||
"font-family: monospace;\n",
|
||
"white-space: pre;\n",
|
||
"display: block;\n",
|
||
"}\n",
|
||
"#unshowable {\n",
|
||
"color: red;\n",
|
||
"font-weight: bold;\n",
|
||
"}\n",
|
||
".err-msg.in.collapse {\n",
|
||
"padding-top: 0.7em;\n",
|
||
"}\n",
|
||
".highlight-code {\n",
|
||
"white-space: pre;\n",
|
||
"font-family: monospace;\n",
|
||
"}\n",
|
||
".suggestion-warning { \n",
|
||
"font-weight: bold;\n",
|
||
"color: rgb(200, 130, 0);\n",
|
||
"}\n",
|
||
".suggestion-error { \n",
|
||
"font-weight: bold;\n",
|
||
"color: red;\n",
|
||
"}\n",
|
||
".suggestion-name {\n",
|
||
"font-weight: bold;\n",
|
||
"}\n",
|
||
"</style><span class='get-type'>Lens :: * -> * -> * -> * -> *</span>"
|
||
],
|
||
"text/plain": [
|
||
"Lens :: * -> * -> * -> * -> *"
|
||
]
|
||
},
|
||
"metadata": {},
|
||
"output_type": "display_data"
|
||
},
|
||
{
|
||
"data": {
|
||
"text/html": [
|
||
"<style>/* Styles used for the Hoogle display in the pager */\n",
|
||
".hoogle-doc {\n",
|
||
"display: block;\n",
|
||
"padding-bottom: 1.3em;\n",
|
||
"padding-left: 0.4em;\n",
|
||
"}\n",
|
||
".hoogle-code {\n",
|
||
"display: block;\n",
|
||
"font-family: monospace;\n",
|
||
"white-space: pre;\n",
|
||
"}\n",
|
||
".hoogle-text {\n",
|
||
"display: block;\n",
|
||
"}\n",
|
||
".hoogle-name {\n",
|
||
"color: green;\n",
|
||
"font-weight: bold;\n",
|
||
"}\n",
|
||
".hoogle-head {\n",
|
||
"font-weight: bold;\n",
|
||
"}\n",
|
||
".hoogle-sub {\n",
|
||
"display: block;\n",
|
||
"margin-left: 0.4em;\n",
|
||
"}\n",
|
||
".hoogle-package {\n",
|
||
"font-weight: bold;\n",
|
||
"font-style: italic;\n",
|
||
"}\n",
|
||
".hoogle-module {\n",
|
||
"font-weight: bold;\n",
|
||
"}\n",
|
||
".hoogle-class {\n",
|
||
"font-weight: bold;\n",
|
||
"}\n",
|
||
".get-type {\n",
|
||
"color: green;\n",
|
||
"font-weight: bold;\n",
|
||
"font-family: monospace;\n",
|
||
"display: block;\n",
|
||
"white-space: pre-wrap;\n",
|
||
"}\n",
|
||
".show-type {\n",
|
||
"color: green;\n",
|
||
"font-weight: bold;\n",
|
||
"font-family: monospace;\n",
|
||
"margin-left: 1em;\n",
|
||
"}\n",
|
||
".mono {\n",
|
||
"font-family: monospace;\n",
|
||
"display: block;\n",
|
||
"}\n",
|
||
".err-msg {\n",
|
||
"color: red;\n",
|
||
"font-style: italic;\n",
|
||
"font-family: monospace;\n",
|
||
"white-space: pre;\n",
|
||
"display: block;\n",
|
||
"}\n",
|
||
"#unshowable {\n",
|
||
"color: red;\n",
|
||
"font-weight: bold;\n",
|
||
"}\n",
|
||
".err-msg.in.collapse {\n",
|
||
"padding-top: 0.7em;\n",
|
||
"}\n",
|
||
".highlight-code {\n",
|
||
"white-space: pre;\n",
|
||
"font-family: monospace;\n",
|
||
"}\n",
|
||
".suggestion-warning { \n",
|
||
"font-weight: bold;\n",
|
||
"color: rgb(200, 130, 0);\n",
|
||
"}\n",
|
||
".suggestion-error { \n",
|
||
"font-weight: bold;\n",
|
||
"color: red;\n",
|
||
"}\n",
|
||
".suggestion-name {\n",
|
||
"font-weight: bold;\n",
|
||
"}\n",
|
||
"</style><span class='get-type'>_2 :: forall s t a b (f :: * -> *). (Field2 s t a b, Functor f) => (a -> f b) -> s -> f t</span>"
|
||
],
|
||
"text/plain": [
|
||
"_2 :: forall s t a b (f :: * -> *). (Field2 s t a b, Functor f) => (a -> f b) -> s -> f t"
|
||
]
|
||
},
|
||
"metadata": {},
|
||
"output_type": "display_data"
|
||
},
|
||
{
|
||
"data": {
|
||
"text/html": [
|
||
"<style>/* Styles used for the Hoogle display in the pager */\n",
|
||
".hoogle-doc {\n",
|
||
"display: block;\n",
|
||
"padding-bottom: 1.3em;\n",
|
||
"padding-left: 0.4em;\n",
|
||
"}\n",
|
||
".hoogle-code {\n",
|
||
"display: block;\n",
|
||
"font-family: monospace;\n",
|
||
"white-space: pre;\n",
|
||
"}\n",
|
||
".hoogle-text {\n",
|
||
"display: block;\n",
|
||
"}\n",
|
||
".hoogle-name {\n",
|
||
"color: green;\n",
|
||
"font-weight: bold;\n",
|
||
"}\n",
|
||
".hoogle-head {\n",
|
||
"font-weight: bold;\n",
|
||
"}\n",
|
||
".hoogle-sub {\n",
|
||
"display: block;\n",
|
||
"margin-left: 0.4em;\n",
|
||
"}\n",
|
||
".hoogle-package {\n",
|
||
"font-weight: bold;\n",
|
||
"font-style: italic;\n",
|
||
"}\n",
|
||
".hoogle-module {\n",
|
||
"font-weight: bold;\n",
|
||
"}\n",
|
||
".hoogle-class {\n",
|
||
"font-weight: bold;\n",
|
||
"}\n",
|
||
".get-type {\n",
|
||
"color: green;\n",
|
||
"font-weight: bold;\n",
|
||
"font-family: monospace;\n",
|
||
"display: block;\n",
|
||
"white-space: pre-wrap;\n",
|
||
"}\n",
|
||
".show-type {\n",
|
||
"color: green;\n",
|
||
"font-weight: bold;\n",
|
||
"font-family: monospace;\n",
|
||
"margin-left: 1em;\n",
|
||
"}\n",
|
||
".mono {\n",
|
||
"font-family: monospace;\n",
|
||
"display: block;\n",
|
||
"}\n",
|
||
".err-msg {\n",
|
||
"color: red;\n",
|
||
"font-style: italic;\n",
|
||
"font-family: monospace;\n",
|
||
"white-space: pre;\n",
|
||
"display: block;\n",
|
||
"}\n",
|
||
"#unshowable {\n",
|
||
"color: red;\n",
|
||
"font-weight: bold;\n",
|
||
"}\n",
|
||
".err-msg.in.collapse {\n",
|
||
"padding-top: 0.7em;\n",
|
||
"}\n",
|
||
".highlight-code {\n",
|
||
"white-space: pre;\n",
|
||
"font-family: monospace;\n",
|
||
"}\n",
|
||
".suggestion-warning { \n",
|
||
"font-weight: bold;\n",
|
||
"color: rgb(200, 130, 0);\n",
|
||
"}\n",
|
||
".suggestion-error { \n",
|
||
"font-weight: bold;\n",
|
||
"color: red;\n",
|
||
"}\n",
|
||
".suggestion-name {\n",
|
||
"font-weight: bold;\n",
|
||
"}\n",
|
||
"</style><span class='get-type'>view :: forall s (m :: * -> *) a. MonadReader s m => Getting a s a -> m a</span>"
|
||
],
|
||
"text/plain": [
|
||
"view :: forall s (m :: * -> *) a. MonadReader s m => Getting a s a -> m a"
|
||
]
|
||
},
|
||
"metadata": {},
|
||
"output_type": "display_data"
|
||
},
|
||
{
|
||
"data": {
|
||
"text/plain": [
|
||
"'a'"
|
||
]
|
||
},
|
||
"metadata": {},
|
||
"output_type": "display_data"
|
||
},
|
||
{
|
||
"data": {
|
||
"text/plain": [
|
||
"'b'"
|
||
]
|
||
},
|
||
"metadata": {},
|
||
"output_type": "display_data"
|
||
}
|
||
],
|
||
"source": [
|
||
":t _1\n",
|
||
"\n",
|
||
":k Lens'\n",
|
||
":k Lens\n",
|
||
"\n",
|
||
"-- _1 :: Lens' (a, b) a\n",
|
||
"-- (a, b) --> Type of structure\n",
|
||
"-- a --> Focus within it\n",
|
||
"\n",
|
||
":t _2\n",
|
||
"\n",
|
||
":t view\n",
|
||
"\n",
|
||
"-- A lens on it's own isn't enough. We need an action to perform on it.\n",
|
||
"\n",
|
||
"-- view :: Lens' s a -> s -> a\n",
|
||
"-- Get the path's focus from within the structure\n",
|
||
"\n",
|
||
"view _1 ('a', 'b')\n",
|
||
"\n",
|
||
"view _2 ('a', 'b')"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"### Setting through a lens"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": 28,
|
||
"metadata": {},
|
||
"outputs": [
|
||
{
|
||
"data": {
|
||
"text/html": [
|
||
"<style>/* Styles used for the Hoogle display in the pager */\n",
|
||
".hoogle-doc {\n",
|
||
"display: block;\n",
|
||
"padding-bottom: 1.3em;\n",
|
||
"padding-left: 0.4em;\n",
|
||
"}\n",
|
||
".hoogle-code {\n",
|
||
"display: block;\n",
|
||
"font-family: monospace;\n",
|
||
"white-space: pre;\n",
|
||
"}\n",
|
||
".hoogle-text {\n",
|
||
"display: block;\n",
|
||
"}\n",
|
||
".hoogle-name {\n",
|
||
"color: green;\n",
|
||
"font-weight: bold;\n",
|
||
"}\n",
|
||
".hoogle-head {\n",
|
||
"font-weight: bold;\n",
|
||
"}\n",
|
||
".hoogle-sub {\n",
|
||
"display: block;\n",
|
||
"margin-left: 0.4em;\n",
|
||
"}\n",
|
||
".hoogle-package {\n",
|
||
"font-weight: bold;\n",
|
||
"font-style: italic;\n",
|
||
"}\n",
|
||
".hoogle-module {\n",
|
||
"font-weight: bold;\n",
|
||
"}\n",
|
||
".hoogle-class {\n",
|
||
"font-weight: bold;\n",
|
||
"}\n",
|
||
".get-type {\n",
|
||
"color: green;\n",
|
||
"font-weight: bold;\n",
|
||
"font-family: monospace;\n",
|
||
"display: block;\n",
|
||
"white-space: pre-wrap;\n",
|
||
"}\n",
|
||
".show-type {\n",
|
||
"color: green;\n",
|
||
"font-weight: bold;\n",
|
||
"font-family: monospace;\n",
|
||
"margin-left: 1em;\n",
|
||
"}\n",
|
||
".mono {\n",
|
||
"font-family: monospace;\n",
|
||
"display: block;\n",
|
||
"}\n",
|
||
".err-msg {\n",
|
||
"color: red;\n",
|
||
"font-style: italic;\n",
|
||
"font-family: monospace;\n",
|
||
"white-space: pre;\n",
|
||
"display: block;\n",
|
||
"}\n",
|
||
"#unshowable {\n",
|
||
"color: red;\n",
|
||
"font-weight: bold;\n",
|
||
"}\n",
|
||
".err-msg.in.collapse {\n",
|
||
"padding-top: 0.7em;\n",
|
||
"}\n",
|
||
".highlight-code {\n",
|
||
"white-space: pre;\n",
|
||
"font-family: monospace;\n",
|
||
"}\n",
|
||
".suggestion-warning { \n",
|
||
"font-weight: bold;\n",
|
||
"color: rgb(200, 130, 0);\n",
|
||
"}\n",
|
||
".suggestion-error { \n",
|
||
"font-weight: bold;\n",
|
||
"color: red;\n",
|
||
"}\n",
|
||
".suggestion-name {\n",
|
||
"font-weight: bold;\n",
|
||
"}\n",
|
||
"</style><span class='get-type'>set :: forall s t a b. ASetter s t a b -> b -> s -> t</span>"
|
||
],
|
||
"text/plain": [
|
||
"set :: forall s t a b. ASetter s t a b -> b -> s -> t"
|
||
]
|
||
},
|
||
"metadata": {},
|
||
"output_type": "display_data"
|
||
},
|
||
{
|
||
"data": {
|
||
"text/html": [
|
||
"<style>/* Styles used for the Hoogle display in the pager */\n",
|
||
".hoogle-doc {\n",
|
||
"display: block;\n",
|
||
"padding-bottom: 1.3em;\n",
|
||
"padding-left: 0.4em;\n",
|
||
"}\n",
|
||
".hoogle-code {\n",
|
||
"display: block;\n",
|
||
"font-family: monospace;\n",
|
||
"white-space: pre;\n",
|
||
"}\n",
|
||
".hoogle-text {\n",
|
||
"display: block;\n",
|
||
"}\n",
|
||
".hoogle-name {\n",
|
||
"color: green;\n",
|
||
"font-weight: bold;\n",
|
||
"}\n",
|
||
".hoogle-head {\n",
|
||
"font-weight: bold;\n",
|
||
"}\n",
|
||
".hoogle-sub {\n",
|
||
"display: block;\n",
|
||
"margin-left: 0.4em;\n",
|
||
"}\n",
|
||
".hoogle-package {\n",
|
||
"font-weight: bold;\n",
|
||
"font-style: italic;\n",
|
||
"}\n",
|
||
".hoogle-module {\n",
|
||
"font-weight: bold;\n",
|
||
"}\n",
|
||
".hoogle-class {\n",
|
||
"font-weight: bold;\n",
|
||
"}\n",
|
||
".get-type {\n",
|
||
"color: green;\n",
|
||
"font-weight: bold;\n",
|
||
"font-family: monospace;\n",
|
||
"display: block;\n",
|
||
"white-space: pre-wrap;\n",
|
||
"}\n",
|
||
".show-type {\n",
|
||
"color: green;\n",
|
||
"font-weight: bold;\n",
|
||
"font-family: monospace;\n",
|
||
"margin-left: 1em;\n",
|
||
"}\n",
|
||
".mono {\n",
|
||
"font-family: monospace;\n",
|
||
"display: block;\n",
|
||
"}\n",
|
||
".err-msg {\n",
|
||
"color: red;\n",
|
||
"font-style: italic;\n",
|
||
"font-family: monospace;\n",
|
||
"white-space: pre;\n",
|
||
"display: block;\n",
|
||
"}\n",
|
||
"#unshowable {\n",
|
||
"color: red;\n",
|
||
"font-weight: bold;\n",
|
||
"}\n",
|
||
".err-msg.in.collapse {\n",
|
||
"padding-top: 0.7em;\n",
|
||
"}\n",
|
||
".highlight-code {\n",
|
||
"white-space: pre;\n",
|
||
"font-family: monospace;\n",
|
||
"}\n",
|
||
".suggestion-warning { \n",
|
||
"font-weight: bold;\n",
|
||
"color: rgb(200, 130, 0);\n",
|
||
"}\n",
|
||
".suggestion-error { \n",
|
||
"font-weight: bold;\n",
|
||
"color: red;\n",
|
||
"}\n",
|
||
".suggestion-name {\n",
|
||
"font-weight: bold;\n",
|
||
"}\n",
|
||
"</style><span class='get-type'>over :: forall s t a b. ASetter s t a b -> (a -> b) -> s -> t</span>"
|
||
],
|
||
"text/plain": [
|
||
"over :: forall s t a b. ASetter s t a b -> (a -> b) -> s -> t"
|
||
]
|
||
},
|
||
"metadata": {},
|
||
"output_type": "display_data"
|
||
},
|
||
{
|
||
"data": {
|
||
"text/plain": [
|
||
"('x','b')"
|
||
]
|
||
},
|
||
"metadata": {},
|
||
"output_type": "display_data"
|
||
},
|
||
{
|
||
"data": {
|
||
"text/plain": [
|
||
"(100,2)"
|
||
]
|
||
},
|
||
"metadata": {},
|
||
"output_type": "display_data"
|
||
}
|
||
],
|
||
"source": [
|
||
"-- set :: Lens' s a -> a -> s -> s\n",
|
||
"-- Set a new value at the path’s focus, leaving the rest of the structure unaltered.\n",
|
||
"\n",
|
||
"-- over :: Lens' s a -> (a -> a) -> s -> s\n",
|
||
"-- Modify the focus of a path by running a function over it, altering it in-place and leaving the\n",
|
||
"-- rest of the structure unaltered.\n",
|
||
"\n",
|
||
":t set\n",
|
||
":t over\n",
|
||
"\n",
|
||
"set _1 'x' ('a', 'b')\n",
|
||
"\n",
|
||
"over _1 (*100) (1, 2)"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"## Exercises - Lens Actions"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": 30,
|
||
"metadata": {},
|
||
"outputs": [
|
||
{
|
||
"data": {
|
||
"text/plain": [
|
||
"'c'"
|
||
]
|
||
},
|
||
"metadata": {},
|
||
"output_type": "display_data"
|
||
},
|
||
{
|
||
"data": {
|
||
"text/plain": [
|
||
"(False,20)"
|
||
]
|
||
},
|
||
"metadata": {},
|
||
"output_type": "display_data"
|
||
}
|
||
],
|
||
"source": [
|
||
"-- 1. Find structure & focus in the following lens\n",
|
||
"\n",
|
||
"-- Lens' (Bool, (Int, String)) Int\n",
|
||
"\n",
|
||
"-- (Bool, (Int, String)) is the structure\n",
|
||
"-- Focus is Int, the 1st member of the 2nd member of the complete structure\n",
|
||
"\n",
|
||
"-- 2. Write the type signature of a Lens with the structure (Char, Int) and the focus Char\n",
|
||
"\n",
|
||
"-- Lens' (Char, Int) Char\n",
|
||
"\n",
|
||
"-- 3. Name three actions we can use on a Lens\n",
|
||
"\n",
|
||
"-- set\n",
|
||
"-- view\n",
|
||
"-- over\n",
|
||
"\n",
|
||
"-- 4\n",
|
||
"\n",
|
||
"view _3 ('a', 'b', 'c')\n",
|
||
"\n",
|
||
"over _2 (*10) (False, 2)"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"## Lenses and records\n",
|
||
"\n",
|
||
"* Lenses subsume the accessor pattern in other languages."
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": 47,
|
||
"metadata": {},
|
||
"outputs": [
|
||
{
|
||
"data": {
|
||
"text/html": [
|
||
"<style>/* Styles used for the Hoogle display in the pager */\n",
|
||
".hoogle-doc {\n",
|
||
"display: block;\n",
|
||
"padding-bottom: 1.3em;\n",
|
||
"padding-left: 0.4em;\n",
|
||
"}\n",
|
||
".hoogle-code {\n",
|
||
"display: block;\n",
|
||
"font-family: monospace;\n",
|
||
"white-space: pre;\n",
|
||
"}\n",
|
||
".hoogle-text {\n",
|
||
"display: block;\n",
|
||
"}\n",
|
||
".hoogle-name {\n",
|
||
"color: green;\n",
|
||
"font-weight: bold;\n",
|
||
"}\n",
|
||
".hoogle-head {\n",
|
||
"font-weight: bold;\n",
|
||
"}\n",
|
||
".hoogle-sub {\n",
|
||
"display: block;\n",
|
||
"margin-left: 0.4em;\n",
|
||
"}\n",
|
||
".hoogle-package {\n",
|
||
"font-weight: bold;\n",
|
||
"font-style: italic;\n",
|
||
"}\n",
|
||
".hoogle-module {\n",
|
||
"font-weight: bold;\n",
|
||
"}\n",
|
||
".hoogle-class {\n",
|
||
"font-weight: bold;\n",
|
||
"}\n",
|
||
".get-type {\n",
|
||
"color: green;\n",
|
||
"font-weight: bold;\n",
|
||
"font-family: monospace;\n",
|
||
"display: block;\n",
|
||
"white-space: pre-wrap;\n",
|
||
"}\n",
|
||
".show-type {\n",
|
||
"color: green;\n",
|
||
"font-weight: bold;\n",
|
||
"font-family: monospace;\n",
|
||
"margin-left: 1em;\n",
|
||
"}\n",
|
||
".mono {\n",
|
||
"font-family: monospace;\n",
|
||
"display: block;\n",
|
||
"}\n",
|
||
".err-msg {\n",
|
||
"color: red;\n",
|
||
"font-style: italic;\n",
|
||
"font-family: monospace;\n",
|
||
"white-space: pre;\n",
|
||
"display: block;\n",
|
||
"}\n",
|
||
"#unshowable {\n",
|
||
"color: red;\n",
|
||
"font-weight: bold;\n",
|
||
"}\n",
|
||
".err-msg.in.collapse {\n",
|
||
"padding-top: 0.7em;\n",
|
||
"}\n",
|
||
".highlight-code {\n",
|
||
"white-space: pre;\n",
|
||
"font-family: monospace;\n",
|
||
"}\n",
|
||
".suggestion-warning { \n",
|
||
"font-weight: bold;\n",
|
||
"color: rgb(200, 130, 0);\n",
|
||
"}\n",
|
||
".suggestion-error { \n",
|
||
"font-weight: bold;\n",
|
||
"color: red;\n",
|
||
"}\n",
|
||
".suggestion-name {\n",
|
||
"font-weight: bold;\n",
|
||
"}\n",
|
||
"</style><span class='get-type'>lens :: forall (f :: * -> *) s a b t. Functor f => (s -> a) -> (s -> b -> t) -> (a -> f b) -> s -> f t</span>"
|
||
],
|
||
"text/plain": [
|
||
"lens :: forall (f :: * -> *) s a b t. Functor f => (s -> a) -> (s -> b -> t) -> (a -> f b) -> s -> f t"
|
||
]
|
||
},
|
||
"metadata": {},
|
||
"output_type": "display_data"
|
||
},
|
||
{
|
||
"data": {
|
||
"text/html": [
|
||
"<style>/* Styles used for the Hoogle display in the pager */\n",
|
||
".hoogle-doc {\n",
|
||
"display: block;\n",
|
||
"padding-bottom: 1.3em;\n",
|
||
"padding-left: 0.4em;\n",
|
||
"}\n",
|
||
".hoogle-code {\n",
|
||
"display: block;\n",
|
||
"font-family: monospace;\n",
|
||
"white-space: pre;\n",
|
||
"}\n",
|
||
".hoogle-text {\n",
|
||
"display: block;\n",
|
||
"}\n",
|
||
".hoogle-name {\n",
|
||
"color: green;\n",
|
||
"font-weight: bold;\n",
|
||
"}\n",
|
||
".hoogle-head {\n",
|
||
"font-weight: bold;\n",
|
||
"}\n",
|
||
".hoogle-sub {\n",
|
||
"display: block;\n",
|
||
"margin-left: 0.4em;\n",
|
||
"}\n",
|
||
".hoogle-package {\n",
|
||
"font-weight: bold;\n",
|
||
"font-style: italic;\n",
|
||
"}\n",
|
||
".hoogle-module {\n",
|
||
"font-weight: bold;\n",
|
||
"}\n",
|
||
".hoogle-class {\n",
|
||
"font-weight: bold;\n",
|
||
"}\n",
|
||
".get-type {\n",
|
||
"color: green;\n",
|
||
"font-weight: bold;\n",
|
||
"font-family: monospace;\n",
|
||
"display: block;\n",
|
||
"white-space: pre-wrap;\n",
|
||
"}\n",
|
||
".show-type {\n",
|
||
"color: green;\n",
|
||
"font-weight: bold;\n",
|
||
"font-family: monospace;\n",
|
||
"margin-left: 1em;\n",
|
||
"}\n",
|
||
".mono {\n",
|
||
"font-family: monospace;\n",
|
||
"display: block;\n",
|
||
"}\n",
|
||
".err-msg {\n",
|
||
"color: red;\n",
|
||
"font-style: italic;\n",
|
||
"font-family: monospace;\n",
|
||
"white-space: pre;\n",
|
||
"display: block;\n",
|
||
"}\n",
|
||
"#unshowable {\n",
|
||
"color: red;\n",
|
||
"font-weight: bold;\n",
|
||
"}\n",
|
||
".err-msg.in.collapse {\n",
|
||
"padding-top: 0.7em;\n",
|
||
"}\n",
|
||
".highlight-code {\n",
|
||
"white-space: pre;\n",
|
||
"font-family: monospace;\n",
|
||
"}\n",
|
||
".suggestion-warning { \n",
|
||
"font-weight: bold;\n",
|
||
"color: rgb(200, 130, 0);\n",
|
||
"}\n",
|
||
".suggestion-error { \n",
|
||
"font-weight: bold;\n",
|
||
"color: red;\n",
|
||
"}\n",
|
||
".suggestion-name {\n",
|
||
"font-weight: bold;\n",
|
||
"}\n",
|
||
"</style><span class='get-type'>Lens :: * -> * -> * -> * -> *</span>"
|
||
],
|
||
"text/plain": [
|
||
"Lens :: * -> * -> * -> * -> *"
|
||
]
|
||
},
|
||
"metadata": {},
|
||
"output_type": "display_data"
|
||
},
|
||
{
|
||
"data": {
|
||
"text/html": [
|
||
"<style>/* Styles used for the Hoogle display in the pager */\n",
|
||
".hoogle-doc {\n",
|
||
"display: block;\n",
|
||
"padding-bottom: 1.3em;\n",
|
||
"padding-left: 0.4em;\n",
|
||
"}\n",
|
||
".hoogle-code {\n",
|
||
"display: block;\n",
|
||
"font-family: monospace;\n",
|
||
"white-space: pre;\n",
|
||
"}\n",
|
||
".hoogle-text {\n",
|
||
"display: block;\n",
|
||
"}\n",
|
||
".hoogle-name {\n",
|
||
"color: green;\n",
|
||
"font-weight: bold;\n",
|
||
"}\n",
|
||
".hoogle-head {\n",
|
||
"font-weight: bold;\n",
|
||
"}\n",
|
||
".hoogle-sub {\n",
|
||
"display: block;\n",
|
||
"margin-left: 0.4em;\n",
|
||
"}\n",
|
||
".hoogle-package {\n",
|
||
"font-weight: bold;\n",
|
||
"font-style: italic;\n",
|
||
"}\n",
|
||
".hoogle-module {\n",
|
||
"font-weight: bold;\n",
|
||
"}\n",
|
||
".hoogle-class {\n",
|
||
"font-weight: bold;\n",
|
||
"}\n",
|
||
".get-type {\n",
|
||
"color: green;\n",
|
||
"font-weight: bold;\n",
|
||
"font-family: monospace;\n",
|
||
"display: block;\n",
|
||
"white-space: pre-wrap;\n",
|
||
"}\n",
|
||
".show-type {\n",
|
||
"color: green;\n",
|
||
"font-weight: bold;\n",
|
||
"font-family: monospace;\n",
|
||
"margin-left: 1em;\n",
|
||
"}\n",
|
||
".mono {\n",
|
||
"font-family: monospace;\n",
|
||
"display: block;\n",
|
||
"}\n",
|
||
".err-msg {\n",
|
||
"color: red;\n",
|
||
"font-style: italic;\n",
|
||
"font-family: monospace;\n",
|
||
"white-space: pre;\n",
|
||
"display: block;\n",
|
||
"}\n",
|
||
"#unshowable {\n",
|
||
"color: red;\n",
|
||
"font-weight: bold;\n",
|
||
"}\n",
|
||
".err-msg.in.collapse {\n",
|
||
"padding-top: 0.7em;\n",
|
||
"}\n",
|
||
".highlight-code {\n",
|
||
"white-space: pre;\n",
|
||
"font-family: monospace;\n",
|
||
"}\n",
|
||
".suggestion-warning { \n",
|
||
"font-weight: bold;\n",
|
||
"color: rgb(200, 130, 0);\n",
|
||
"}\n",
|
||
".suggestion-error { \n",
|
||
"font-weight: bold;\n",
|
||
"color: red;\n",
|
||
"}\n",
|
||
".suggestion-name {\n",
|
||
"font-weight: bold;\n",
|
||
"}\n",
|
||
"</style><span class='get-type'>Lens' :: * -> * -> *</span>"
|
||
],
|
||
"text/plain": [
|
||
"Lens' :: * -> * -> *"
|
||
]
|
||
},
|
||
"metadata": {},
|
||
"output_type": "display_data"
|
||
}
|
||
],
|
||
"source": [
|
||
"-- Just changed the names from the example in the book\n",
|
||
"data Name = \n",
|
||
" Name { _name :: String\n",
|
||
" , _age :: Int\n",
|
||
" } deriving (Show)\n",
|
||
" \n",
|
||
"-- lens :: (s -> a) -> (s -> b -> t) -> Lens s t a b\n",
|
||
"-- lens :: (s -> a) -> (s -> a -> s) -> Lens' s a\n",
|
||
"\n",
|
||
":t lens\n",
|
||
":k Lens\n",
|
||
":k Lens'\n",
|
||
"\n",
|
||
"-- Whenever you see 's' in a Lens thing 'structure' and when you see 'a', think 'focus'.\n",
|
||
"\n",
|
||
"-- getAge :: s -> a\n",
|
||
"getAge :: Name -> Int\n",
|
||
"getAge = _age\n",
|
||
"\n",
|
||
"-- setAge :: s -> a -> s\n",
|
||
"setAge :: Name -> Int -> Name\n",
|
||
"setAge name newAge = name { _age = newAge }\n",
|
||
"\n",
|
||
"numAge :: Lens' Name Int\n",
|
||
"numAge = lens getAge setAge"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"## Exercises - Records Part One"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": 62,
|
||
"metadata": {},
|
||
"outputs": [
|
||
{
|
||
"data": {
|
||
"text/plain": [
|
||
"31"
|
||
]
|
||
},
|
||
"metadata": {},
|
||
"output_type": "display_data"
|
||
},
|
||
{
|
||
"data": {
|
||
"text/plain": [
|
||
"Name {_name = \"Sanchayan Maity\", _age = 32}"
|
||
]
|
||
},
|
||
"metadata": {},
|
||
"output_type": "display_data"
|
||
},
|
||
{
|
||
"data": {
|
||
"text/plain": [
|
||
"Name {_name = \"Sanchayan Maity\", _age = 34}"
|
||
]
|
||
},
|
||
"metadata": {},
|
||
"output_type": "display_data"
|
||
},
|
||
{
|
||
"data": {
|
||
"text/plain": [
|
||
"Name {_name = \"Sanchayan Maity\", _age = 34}"
|
||
]
|
||
},
|
||
"metadata": {},
|
||
"output_type": "display_data"
|
||
},
|
||
{
|
||
"data": {
|
||
"text/plain": [
|
||
"\"Sanchayan Maity\""
|
||
]
|
||
},
|
||
"metadata": {},
|
||
"output_type": "display_data"
|
||
},
|
||
{
|
||
"data": {
|
||
"text/plain": [
|
||
"Name {_name = \"Foo\", _age = 31}"
|
||
]
|
||
},
|
||
"metadata": {},
|
||
"output_type": "display_data"
|
||
},
|
||
{
|
||
"data": {
|
||
"text/plain": [
|
||
"Name {_name = \"Boo Sanchayan Maity\", _age = 31}"
|
||
]
|
||
},
|
||
"metadata": {},
|
||
"output_type": "display_data"
|
||
}
|
||
],
|
||
"source": [
|
||
"-- 1. The structure and focus of a lens are typically represented by which letters in type signature\n",
|
||
"-- s and a respectively\n",
|
||
"\n",
|
||
"-- 2. Which two components are required to create a lens\n",
|
||
"-- getter and setter\n",
|
||
"\n",
|
||
"-- Implement the following Lens\n",
|
||
"\n",
|
||
"-- name :: Lens' Name String\n",
|
||
"\n",
|
||
"getName :: Name -> String\n",
|
||
"getName = _name\n",
|
||
"\n",
|
||
"setName :: Name -> String -> Name\n",
|
||
"setName name newName = name { _name = newName }\n",
|
||
"\n",
|
||
"name :: Lens' Name String\n",
|
||
"name = lens getName setName\n",
|
||
"\n",
|
||
"myName :: Name\n",
|
||
"myName = Name { _name = \"Sanchayan Maity\"\n",
|
||
" , _age = 31 } \n",
|
||
" \n",
|
||
"-- Getting, setting & modifying with a field lens\n",
|
||
"\n",
|
||
"-- For Age field\n",
|
||
"view numAge myName\n",
|
||
"set numAge 32 myName\n",
|
||
"over numAge (+3) myName\n",
|
||
"set numAge (view numAge myName + 3) myName\n",
|
||
"\n",
|
||
"-- For Name field\n",
|
||
"view name myName\n",
|
||
"set name \"Foo\" myName\n",
|
||
"over name (\"Boo \" ++) myName"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"## Automatically generating field names"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": 67,
|
||
"metadata": {},
|
||
"outputs": [
|
||
{
|
||
"data": {
|
||
"text/html": [
|
||
"<style>/* Styles used for the Hoogle display in the pager */\n",
|
||
".hoogle-doc {\n",
|
||
"display: block;\n",
|
||
"padding-bottom: 1.3em;\n",
|
||
"padding-left: 0.4em;\n",
|
||
"}\n",
|
||
".hoogle-code {\n",
|
||
"display: block;\n",
|
||
"font-family: monospace;\n",
|
||
"white-space: pre;\n",
|
||
"}\n",
|
||
".hoogle-text {\n",
|
||
"display: block;\n",
|
||
"}\n",
|
||
".hoogle-name {\n",
|
||
"color: green;\n",
|
||
"font-weight: bold;\n",
|
||
"}\n",
|
||
".hoogle-head {\n",
|
||
"font-weight: bold;\n",
|
||
"}\n",
|
||
".hoogle-sub {\n",
|
||
"display: block;\n",
|
||
"margin-left: 0.4em;\n",
|
||
"}\n",
|
||
".hoogle-package {\n",
|
||
"font-weight: bold;\n",
|
||
"font-style: italic;\n",
|
||
"}\n",
|
||
".hoogle-module {\n",
|
||
"font-weight: bold;\n",
|
||
"}\n",
|
||
".hoogle-class {\n",
|
||
"font-weight: bold;\n",
|
||
"}\n",
|
||
".get-type {\n",
|
||
"color: green;\n",
|
||
"font-weight: bold;\n",
|
||
"font-family: monospace;\n",
|
||
"display: block;\n",
|
||
"white-space: pre-wrap;\n",
|
||
"}\n",
|
||
".show-type {\n",
|
||
"color: green;\n",
|
||
"font-weight: bold;\n",
|
||
"font-family: monospace;\n",
|
||
"margin-left: 1em;\n",
|
||
"}\n",
|
||
".mono {\n",
|
||
"font-family: monospace;\n",
|
||
"display: block;\n",
|
||
"}\n",
|
||
".err-msg {\n",
|
||
"color: red;\n",
|
||
"font-style: italic;\n",
|
||
"font-family: monospace;\n",
|
||
"white-space: pre;\n",
|
||
"display: block;\n",
|
||
"}\n",
|
||
"#unshowable {\n",
|
||
"color: red;\n",
|
||
"font-weight: bold;\n",
|
||
"}\n",
|
||
".err-msg.in.collapse {\n",
|
||
"padding-top: 0.7em;\n",
|
||
"}\n",
|
||
".highlight-code {\n",
|
||
"white-space: pre;\n",
|
||
"font-family: monospace;\n",
|
||
"}\n",
|
||
".suggestion-warning { \n",
|
||
"font-weight: bold;\n",
|
||
"color: rgb(200, 130, 0);\n",
|
||
"}\n",
|
||
".suggestion-error { \n",
|
||
"font-weight: bold;\n",
|
||
"color: red;\n",
|
||
"}\n",
|
||
".suggestion-name {\n",
|
||
"font-weight: bold;\n",
|
||
"}\n",
|
||
"</style><span class='get-type'>name :: forall (f :: * -> *). Functor f => (String -> f String) -> Ship -> f Ship</span>"
|
||
],
|
||
"text/plain": [
|
||
"name :: forall (f :: * -> *). Functor f => (String -> f String) -> Ship -> f Ship"
|
||
]
|
||
},
|
||
"metadata": {},
|
||
"output_type": "display_data"
|
||
},
|
||
{
|
||
"data": {
|
||
"text/html": [
|
||
"<style>/* Styles used for the Hoogle display in the pager */\n",
|
||
".hoogle-doc {\n",
|
||
"display: block;\n",
|
||
"padding-bottom: 1.3em;\n",
|
||
"padding-left: 0.4em;\n",
|
||
"}\n",
|
||
".hoogle-code {\n",
|
||
"display: block;\n",
|
||
"font-family: monospace;\n",
|
||
"white-space: pre;\n",
|
||
"}\n",
|
||
".hoogle-text {\n",
|
||
"display: block;\n",
|
||
"}\n",
|
||
".hoogle-name {\n",
|
||
"color: green;\n",
|
||
"font-weight: bold;\n",
|
||
"}\n",
|
||
".hoogle-head {\n",
|
||
"font-weight: bold;\n",
|
||
"}\n",
|
||
".hoogle-sub {\n",
|
||
"display: block;\n",
|
||
"margin-left: 0.4em;\n",
|
||
"}\n",
|
||
".hoogle-package {\n",
|
||
"font-weight: bold;\n",
|
||
"font-style: italic;\n",
|
||
"}\n",
|
||
".hoogle-module {\n",
|
||
"font-weight: bold;\n",
|
||
"}\n",
|
||
".hoogle-class {\n",
|
||
"font-weight: bold;\n",
|
||
"}\n",
|
||
".get-type {\n",
|
||
"color: green;\n",
|
||
"font-weight: bold;\n",
|
||
"font-family: monospace;\n",
|
||
"display: block;\n",
|
||
"white-space: pre-wrap;\n",
|
||
"}\n",
|
||
".show-type {\n",
|
||
"color: green;\n",
|
||
"font-weight: bold;\n",
|
||
"font-family: monospace;\n",
|
||
"margin-left: 1em;\n",
|
||
"}\n",
|
||
".mono {\n",
|
||
"font-family: monospace;\n",
|
||
"display: block;\n",
|
||
"}\n",
|
||
".err-msg {\n",
|
||
"color: red;\n",
|
||
"font-style: italic;\n",
|
||
"font-family: monospace;\n",
|
||
"white-space: pre;\n",
|
||
"display: block;\n",
|
||
"}\n",
|
||
"#unshowable {\n",
|
||
"color: red;\n",
|
||
"font-weight: bold;\n",
|
||
"}\n",
|
||
".err-msg.in.collapse {\n",
|
||
"padding-top: 0.7em;\n",
|
||
"}\n",
|
||
".highlight-code {\n",
|
||
"white-space: pre;\n",
|
||
"font-family: monospace;\n",
|
||
"}\n",
|
||
".suggestion-warning { \n",
|
||
"font-weight: bold;\n",
|
||
"color: rgb(200, 130, 0);\n",
|
||
"}\n",
|
||
".suggestion-error { \n",
|
||
"font-weight: bold;\n",
|
||
"color: red;\n",
|
||
"}\n",
|
||
".suggestion-name {\n",
|
||
"font-weight: bold;\n",
|
||
"}\n",
|
||
"</style><span class='get-type'>numCrew :: forall (f :: * -> *). Functor f => (Int -> f Int) -> Ship -> f Ship</span>"
|
||
],
|
||
"text/plain": [
|
||
"numCrew :: forall (f :: * -> *). Functor f => (Int -> f Int) -> Ship -> f Ship"
|
||
]
|
||
},
|
||
"metadata": {},
|
||
"output_type": "display_data"
|
||
},
|
||
{
|
||
"data": {
|
||
"text/html": [
|
||
"<style>/* Styles used for the Hoogle display in the pager */\n",
|
||
".hoogle-doc {\n",
|
||
"display: block;\n",
|
||
"padding-bottom: 1.3em;\n",
|
||
"padding-left: 0.4em;\n",
|
||
"}\n",
|
||
".hoogle-code {\n",
|
||
"display: block;\n",
|
||
"font-family: monospace;\n",
|
||
"white-space: pre;\n",
|
||
"}\n",
|
||
".hoogle-text {\n",
|
||
"display: block;\n",
|
||
"}\n",
|
||
".hoogle-name {\n",
|
||
"color: green;\n",
|
||
"font-weight: bold;\n",
|
||
"}\n",
|
||
".hoogle-head {\n",
|
||
"font-weight: bold;\n",
|
||
"}\n",
|
||
".hoogle-sub {\n",
|
||
"display: block;\n",
|
||
"margin-left: 0.4em;\n",
|
||
"}\n",
|
||
".hoogle-package {\n",
|
||
"font-weight: bold;\n",
|
||
"font-style: italic;\n",
|
||
"}\n",
|
||
".hoogle-module {\n",
|
||
"font-weight: bold;\n",
|
||
"}\n",
|
||
".hoogle-class {\n",
|
||
"font-weight: bold;\n",
|
||
"}\n",
|
||
".get-type {\n",
|
||
"color: green;\n",
|
||
"font-weight: bold;\n",
|
||
"font-family: monospace;\n",
|
||
"display: block;\n",
|
||
"white-space: pre-wrap;\n",
|
||
"}\n",
|
||
".show-type {\n",
|
||
"color: green;\n",
|
||
"font-weight: bold;\n",
|
||
"font-family: monospace;\n",
|
||
"margin-left: 1em;\n",
|
||
"}\n",
|
||
".mono {\n",
|
||
"font-family: monospace;\n",
|
||
"display: block;\n",
|
||
"}\n",
|
||
".err-msg {\n",
|
||
"color: red;\n",
|
||
"font-style: italic;\n",
|
||
"font-family: monospace;\n",
|
||
"white-space: pre;\n",
|
||
"display: block;\n",
|
||
"}\n",
|
||
"#unshowable {\n",
|
||
"color: red;\n",
|
||
"font-weight: bold;\n",
|
||
"}\n",
|
||
".err-msg.in.collapse {\n",
|
||
"padding-top: 0.7em;\n",
|
||
"}\n",
|
||
".highlight-code {\n",
|
||
"white-space: pre;\n",
|
||
"font-family: monospace;\n",
|
||
"}\n",
|
||
".suggestion-warning { \n",
|
||
"font-weight: bold;\n",
|
||
"color: rgb(200, 130, 0);\n",
|
||
"}\n",
|
||
".suggestion-error { \n",
|
||
"font-weight: bold;\n",
|
||
"color: red;\n",
|
||
"}\n",
|
||
".suggestion-name {\n",
|
||
"font-weight: bold;\n",
|
||
"}\n",
|
||
"</style><span class='get-type'>getNumCrew :: Ship -> Int</span>"
|
||
],
|
||
"text/plain": [
|
||
"getNumCrew :: Ship -> Int"
|
||
]
|
||
},
|
||
"metadata": {},
|
||
"output_type": "display_data"
|
||
}
|
||
],
|
||
"source": [
|
||
"data Ship = \n",
|
||
" Ship { _name :: String\n",
|
||
" , _numCrew :: Int \n",
|
||
" } deriving (Show)\n",
|
||
"\n",
|
||
"makeLenses ''Ship\n",
|
||
"\n",
|
||
":t name\n",
|
||
":t numCrew\n",
|
||
":t getNumCrew"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"## Exercises - Records Part Two"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": 72,
|
||
"metadata": {},
|
||
"outputs": [],
|
||
"source": [
|
||
"-- data Inventory = \n",
|
||
"-- Inventory { _wand :: Wand\n",
|
||
"-- , _book :: Book\n",
|
||
"-- , _potions :: [Potion] }\n",
|
||
"\n",
|
||
"-- makeLenses ''Inventory\n",
|
||
"\n",
|
||
"-- Lenses generated would be\n",
|
||
"\n",
|
||
"-- wand\n",
|
||
"-- book\n",
|
||
"-- potions\n",
|
||
"-- getWand\n",
|
||
"-- getBook\n",
|
||
"-- getPotions\n",
|
||
"-- setWand\n",
|
||
"-- setBook\n",
|
||
"-- setPotions\n",
|
||
"\n",
|
||
"-- gazork :: Functor f => (Spuzz -> f Spuzz) -> Chumble -> f Chumble\n",
|
||
"-- gazork :: Lens' Chumble Spuzz\n",
|
||
"\n",
|
||
"data Pet = Pet \n",
|
||
" { _petName :: String\n",
|
||
" , _petType :: String\n",
|
||
" }\n",
|
||
" \n",
|
||
"makeLenses ''Pet\n",
|
||
"\n",
|
||
"getPetName :: Pet -> String\n",
|
||
"getPetName = view petName"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"### Lens is an optic which **always** accesses **exactly** one focus"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"### Is it a Lens?\n",
|
||
"\n",
|
||
"* second :: Lens' (a, b, c) b\n",
|
||
"\n",
|
||
"* inMaybe :: Lens' (Maybe a) a\n",
|
||
"\n",
|
||
"* left :: Lens' (Either a b) a\n",
|
||
"\n",
|
||
"* listThird :: Lens' [a] a\n",
|
||
"\n",
|
||
"* Can you write a lens which focuses the second element of a tuple if the Bool in the first slot is True and focuses the third element if it’s False ? conditional :: Lens' (Bool, a, a) a\n",
|
||
"\n",
|
||
"* Consider the below data type. Is it possible to have a lens msg :: Lens' Err String"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": 75,
|
||
"metadata": {},
|
||
"outputs": [],
|
||
"source": [
|
||
"data Err = \n",
|
||
" ReallyBadError { _msg :: String }\n",
|
||
" | ExitCode { _code :: Int }\n"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"## Lens Laws\n",
|
||
"\n",
|
||
"1. You get back what you set\n",
|
||
"2. Setting back what you got doesn't do anything\n",
|
||
"3. Setting twice is the same as setting once"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"## Virtual Fields"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": 82,
|
||
"metadata": {},
|
||
"outputs": [
|
||
{
|
||
"data": {
|
||
"text/html": [
|
||
"<style>/* Styles used for the Hoogle display in the pager */\n",
|
||
".hoogle-doc {\n",
|
||
"display: block;\n",
|
||
"padding-bottom: 1.3em;\n",
|
||
"padding-left: 0.4em;\n",
|
||
"}\n",
|
||
".hoogle-code {\n",
|
||
"display: block;\n",
|
||
"font-family: monospace;\n",
|
||
"white-space: pre;\n",
|
||
"}\n",
|
||
".hoogle-text {\n",
|
||
"display: block;\n",
|
||
"}\n",
|
||
".hoogle-name {\n",
|
||
"color: green;\n",
|
||
"font-weight: bold;\n",
|
||
"}\n",
|
||
".hoogle-head {\n",
|
||
"font-weight: bold;\n",
|
||
"}\n",
|
||
".hoogle-sub {\n",
|
||
"display: block;\n",
|
||
"margin-left: 0.4em;\n",
|
||
"}\n",
|
||
".hoogle-package {\n",
|
||
"font-weight: bold;\n",
|
||
"font-style: italic;\n",
|
||
"}\n",
|
||
".hoogle-module {\n",
|
||
"font-weight: bold;\n",
|
||
"}\n",
|
||
".hoogle-class {\n",
|
||
"font-weight: bold;\n",
|
||
"}\n",
|
||
".get-type {\n",
|
||
"color: green;\n",
|
||
"font-weight: bold;\n",
|
||
"font-family: monospace;\n",
|
||
"display: block;\n",
|
||
"white-space: pre-wrap;\n",
|
||
"}\n",
|
||
".show-type {\n",
|
||
"color: green;\n",
|
||
"font-weight: bold;\n",
|
||
"font-family: monospace;\n",
|
||
"margin-left: 1em;\n",
|
||
"}\n",
|
||
".mono {\n",
|
||
"font-family: monospace;\n",
|
||
"display: block;\n",
|
||
"}\n",
|
||
".err-msg {\n",
|
||
"color: red;\n",
|
||
"font-style: italic;\n",
|
||
"font-family: monospace;\n",
|
||
"white-space: pre;\n",
|
||
"display: block;\n",
|
||
"}\n",
|
||
"#unshowable {\n",
|
||
"color: red;\n",
|
||
"font-weight: bold;\n",
|
||
"}\n",
|
||
".err-msg.in.collapse {\n",
|
||
"padding-top: 0.7em;\n",
|
||
"}\n",
|
||
".highlight-code {\n",
|
||
"white-space: pre;\n",
|
||
"font-family: monospace;\n",
|
||
"}\n",
|
||
".suggestion-warning { \n",
|
||
"font-weight: bold;\n",
|
||
"color: rgb(200, 130, 0);\n",
|
||
"}\n",
|
||
".suggestion-error { \n",
|
||
"font-weight: bold;\n",
|
||
"color: red;\n",
|
||
"}\n",
|
||
".suggestion-name {\n",
|
||
"font-weight: bold;\n",
|
||
"}\n",
|
||
"</style><span class='get-type'>celsius :: forall (f :: * -> *). Functor f => (Float -> f Float) -> Temperature -> f Temperature</span>"
|
||
],
|
||
"text/plain": [
|
||
"celsius :: forall (f :: * -> *). Functor f => (Float -> f Float) -> Temperature -> f Temperature"
|
||
]
|
||
},
|
||
"metadata": {},
|
||
"output_type": "display_data"
|
||
},
|
||
{
|
||
"data": {
|
||
"text/plain": [
|
||
"7.0"
|
||
]
|
||
},
|
||
"metadata": {},
|
||
"output_type": "display_data"
|
||
},
|
||
{
|
||
"data": {
|
||
"text/plain": [
|
||
"Temperature {_location = \"Bangalore\", _celsius = 13.5}"
|
||
]
|
||
},
|
||
"metadata": {},
|
||
"output_type": "display_data"
|
||
},
|
||
{
|
||
"data": {
|
||
"text/plain": [
|
||
"Temperature {_location = \"Bangalore\", _celsius = 17.0}"
|
||
]
|
||
},
|
||
"metadata": {},
|
||
"output_type": "display_data"
|
||
},
|
||
{
|
||
"data": {
|
||
"text/plain": [
|
||
"44.6"
|
||
]
|
||
},
|
||
"metadata": {},
|
||
"output_type": "display_data"
|
||
},
|
||
{
|
||
"data": {
|
||
"text/plain": [
|
||
"Temperature {_location = \"Bangalore\", _celsius = 13.5}"
|
||
]
|
||
},
|
||
"metadata": {},
|
||
"output_type": "display_data"
|
||
},
|
||
{
|
||
"data": {
|
||
"text/plain": [
|
||
"Temperature {_location = \"Bangalore\", _celsius = 17.0}"
|
||
]
|
||
},
|
||
"metadata": {},
|
||
"output_type": "display_data"
|
||
}
|
||
],
|
||
"source": [
|
||
"data Temperature = \n",
|
||
" Temperature { _location :: String\n",
|
||
" , _celsius :: Float\n",
|
||
" } deriving (Show)\n",
|
||
" \n",
|
||
"makeLenses ''Temperature\n",
|
||
"\n",
|
||
":t celsius\n",
|
||
"\n",
|
||
"let temp = Temperature \"Bangalore\" 7.0\n",
|
||
"\n",
|
||
"view celsius temp\n",
|
||
"set celsius 13.5 temp\n",
|
||
"over celsius (+10) temp\n",
|
||
"\n",
|
||
"celsiusToFahrenheit :: Float -> Float\n",
|
||
"celsiusToFahrenheit c = (c * (9/5)) + 32\n",
|
||
"\n",
|
||
"fahrenheitToCelsius :: Float -> Float\n",
|
||
"fahrenheitToCelsius f = (f - 32) * (5/9)\n",
|
||
"\n",
|
||
"fahrenheit :: Lens' Temperature Float\n",
|
||
"fahrenheit = lens getter setter\n",
|
||
" where\n",
|
||
" getter = celsiusToFahrenheit . view celsius\n",
|
||
" setter temp f = set celsius (fahrenheitToCelsius f) temp\n",
|
||
" \n",
|
||
"view fahrenheit temp\n",
|
||
"set fahrenheit 56.3 temp\n",
|
||
"over fahrenheit (+18) temp"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"Note: TODO: The exercises on laws & virtual fields"
|
||
]
|
||
}
|
||
],
|
||
"metadata": {
|
||
"kernelspec": {
|
||
"display_name": "Haskell",
|
||
"language": "haskell",
|
||
"name": "haskell"
|
||
},
|
||
"language_info": {
|
||
"codemirror_mode": "ihaskell",
|
||
"file_extension": ".hs",
|
||
"name": "haskell",
|
||
"pygments_lexer": "Haskell",
|
||
"version": "8.6.5"
|
||
}
|
||
},
|
||
"nbformat": 4,
|
||
"nbformat_minor": 2
|
||
}
|