haskell-notebooks/folds.ipynb
Sanchayan Maity e3beb5ea1d Add folds chapter
Some exercises we need to finish and some we also need to revisit.

Signed-off-by: Sanchayan Maity <maitysanchayan@gmail.com>
2020-01-26 21:23:28 +05:30

4748 lines
117 KiB
Text
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

{
"cells": [
{
"cell_type": "code",
"execution_count": 2,
"metadata": {},
"outputs": [],
"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",
"{-# LANGUAGE OverloadedStrings #-}\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",
"data Role\n",
" = Gunner\n",
" | PowderMonkey\n",
" | Navigator\n",
" | Captain\n",
" | FirstMate\n",
" deriving (Show, Eq, Ord)\n",
" \n",
"data CrewMember =\n",
" CrewMember { _name :: String\n",
" , _role :: Role\n",
" , _talents :: [String]\n",
" } deriving (Show, Eq, Ord)\n",
" \n",
"makeLenses ''CrewMember\n",
"\n",
"roster :: S.Set CrewMember\n",
"roster = S.fromList\n",
" [ CrewMember \"Grumpy Roger\" Gunner [\"Juggling\", \"Arbitrage\"]\n",
" , CrewMember \"Long-John Bronze\" PowderMonkey [\"Origami\"]\n",
" , CrewMember \"Salty Steve\" PowderMonkey [\"Charcuterie\"]\n",
" , CrewMember \"One-eyed jack\" Navigator []\n",
" ]"
]
},
{
"cell_type": "code",
"execution_count": 17,
"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'>folded :: forall (p :: * -> * -> *) (f1 :: * -> *) (f2 :: * -> *) a. (Indexable Int p, Contravariant f1, Foldable f2, Applicative f1) => p a (f1 a) -> f2 a -> f1 (f2 a)</span>"
],
"text/plain": [
"folded :: forall (p :: * -> * -> *) (f1 :: * -> *) (f2 :: * -> *) a. (Indexable Int p, Contravariant f1, Foldable f2, Applicative f1) => p a (f1 a) -> f2 a -> f1 (f2 a)"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"ename": "",
"evalue": "",
"output_type": "error",
"traceback": [
"<interactive>:1:11: error:\n • No instance for (Monoid CrewMember) arising from a use of crewMembers\n • In the second argument of (^.), namely crewMembers\n In the expression: roster ^. crewMembers\n In an equation for it: it = roster ^. crewMembers"
]
}
],
"source": [
"rosterRoles :: Fold (S.Set CrewMember) Role\n",
"rosterRoles = undefined\n",
"\n",
"crewMembers :: Fold (S.Set CrewMember) CrewMember\n",
"crewMembers = folded\n",
"\n",
":t folded\n",
"\n",
"-- folded :: Foldable f => Fold (f a) a\n",
"\n",
"roster ^. crewMembers"
]
},
{
"cell_type": "code",
"execution_count": 16,
"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'>toListOf :: forall a s. Getting (Endo [a]) s a -> s -> [a]</span>"
],
"text/plain": [
"toListOf :: forall a s. Getting (Endo [a]) s a -> s -> [a]"
]
},
"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'>(^..) :: forall s a. s -> Getting (Endo [a]) s a -> [a]</span>"
],
"text/plain": [
"(^..) :: forall s a. s -> Getting (Endo [a]) s a -> [a]"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/plain": [
"[CrewMember {_name = \"Grumpy Roger\", _role = Gunner, _talents = [\"Juggling\",\"Arbitrage\"]},CrewMember {_name = \"Long-John Bronze\", _role = PowderMonkey, _talents = [\"Origami\"]},CrewMember {_name = \"One-eyed jack\", _role = Navigator, _talents = []},CrewMember {_name = \"Salty Steve\", _role = PowderMonkey, _talents = [\"Charcuterie\"]}]"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
":t toListOf\n",
":t (^..)\n",
"\n",
"-- toListOf :: Fold s a -> s -> [a]\n",
"-- (^..) :: s -> Fold s a -> [a]\n",
"\n",
"toListOf crewMembers roster"
]
},
{
"cell_type": "code",
"execution_count": 18,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"[\"Buried Treasure\"]"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/plain": [
"[]"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/plain": [
"[\"Cutlass\"]"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/plain": [
"[\"Gold\"]"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/plain": [
"[\"Captain\",\"First Mate\"]"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"Just \"Buried Treasure\" ^.. folded\n",
"\n",
"Nothing ^.. folded\n",
"\n",
"Identity \"Cutlass\" ^.. folded\n",
"\n",
"(\"Rubies\", \"Gold\") ^.. folded\n",
"\n",
"M.fromList [(\"Jack\", \"Captain\"), (\"Will\", \"First Mate\")] ^.. folded"
]
},
{
"cell_type": "code",
"execution_count": 23,
"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'>role :: forall (f :: * -> *). Functor f => (Role -> f Role) -> CrewMember -> f CrewMember</span>"
],
"text/plain": [
"role :: forall (f :: * -> *). Functor f => (Role -> f Role) -> CrewMember -> f CrewMember"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/plain": [
"[PowderMonkey]"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/plain": [
"[Gunner,PowderMonkey,Navigator,PowderMonkey]"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
":t role\n",
"\n",
"crewRole :: Fold CrewMember Role\n",
"crewRole = role\n",
"\n",
"let jerry = CrewMember \"Jerry\" PowderMonkey [\"Ice Cream Making\"]\n",
"\n",
"jerry ^.. crewRole\n",
"\n",
"-- Lens' s a\n",
"-- becomes\n",
"-- Fold s a\n",
"\n",
"roster ^.. folded . role\n",
"\n",
"-- folded :: Fold (S.Set CrewMember) CrewMember\n",
"-- role :: Fold CrewMember Role"
]
},
{
"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'>both :: forall (r :: * -> * -> *) (f :: * -> *) a b. (Bitraversable r, Applicative f) => (a -> f b) -> r a a -> f (r b b)</span>"
],
"text/plain": [
"both :: forall (r :: * -> * -> *) (f :: * -> *) a b. (Bitraversable r, Applicative f) => (a -> f b) -> r a a -> f (r b b)"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/plain": [
"[\"Gemini\",\"Leo\"]"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/plain": [
"[\"Albuquerque\"]"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/plain": [
"[\"Yosemite\"]"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/plain": [
"[\"Leo\",\"Libra\"]"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
":t both\n",
"\n",
"-- both :: Bitraversable r => Traversal (r a a) (r b b) a b\n",
"-- both :: Bitraversable r => Fold (r a a) a\n",
"\n",
"(\"Gemini\", \"Leo\") ^.. both\n",
"\n",
"Left \"Albuquerque\" ^.. both\n",
"\n",
"Right \"Yosemite\" ^.. both\n",
"\n",
"(\"Gemini\", \"Leo\", \"Libra\") ^.. both"
]
},
{
"cell_type": "code",
"execution_count": 31,
"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'>each :: forall s t a b (f :: * -> *). (Each s t a b, Applicative f) => (a -> f b) -> s -> f t</span>"
],
"text/plain": [
"each :: forall s t a b (f :: * -> *). (Each s t a b, Applicative 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'>traverse :: forall (t :: * -> *) (f :: * -> *) a b. (Traversable t, Applicative f) => (a -> f b) -> t a -> f (t b)</span>"
],
"text/plain": [
"traverse :: forall (t :: * -> *) (f :: * -> *) a b. (Traversable t, Applicative f) => (a -> f b) -> t a -> f (t b)"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/plain": [
"[1,2,3,4,5]"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/plain": [
"[1,2,3,4,5]"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/plain": [
"\"Made him an offer he couldn't refuse\""
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
":t each\n",
"\n",
"-- each :: Each s t a b => Traversal s t a b\n",
"-- each :: Each s s a a => Fold s a\n",
"\n",
":t traverse\n",
"\n",
"(1, 2, 3, 4, 5) ^.. each\n",
"\n",
"[1, 2, 3, 4, 5] ^.. each\n",
"\n",
"(\"Made him an offer he couldn't refuse\" :: T.Text) ^.. each"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Exercises"
]
},
{
"cell_type": "code",
"execution_count": 58,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"[(3,\"Sirens\"),(882,\"Kraken\"),(92,\"Ogopogo\")]"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/plain": [
"[\"Sirens\",\"Kraken\",\"Ogopogo\"]"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/plain": [
"\"SirensKrakenOgopogo\""
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/plain": [
"[\"Sirens\",\"Kraken\",\"Ogopogo\"]"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/plain": [
"[1,2,3,4,5,6]"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/plain": [
"[\"Captain\",\"First Mate\"]"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/plain": [
"[\"Why\",\"So\",\"Serious?\"]"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/plain": [
"\"HelloIt's me\""
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/plain": [
"[(\"Why\",\"So\",\"Serious?\"),(\"This\",\"is\",\"SPARTA\")]"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/plain": [
"[\"Why\",\"So\",\"Serious?\",\"This\",\"is\",\"SPARTA\"]"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/plain": [
"\"WhySoSerious?ThisisSPARTA\""
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/plain": [
"[1,2,3]"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/plain": [
"[\"Light\"]"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/plain": [
"[\"Light\",\"Dark\",\"Happy\",\"Sad\"]"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/plain": [
"[\"Light\",\"Happy\"]"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/plain": [
"\"DarkSad\""
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/plain": [
"[\"Bond\",\"James\",\"Bond\"]"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"-- 1.\n",
"\n",
"beastSizes :: [(Int, String)]\n",
"beastSizes = [(3, \"Sirens\"), (882, \"Kraken\"), (92, \"Ogopogo\")]\n",
"\n",
"beastSizes ^.. folded\n",
"\n",
"beastSizes ^.. folded . folded\n",
"\n",
"beastSizes ^.. folded . folded . folded\n",
"\n",
"beastSizes ^.. folded . _2\n",
"\n",
"toListOf (folded . folded) [[1, 2, 3], [4, 5, 6]]\n",
"\n",
"toListOf (folded . folded) (S.fromList [(\"Jack\", \"Captain\"), (\"Will\", \"First Mate\")])\n",
"\n",
"(\"Why\", \"So\", \"Serious?\") ^.. each\n",
"\n",
"(\"Hello\" :: String, \"It's me\" :: String) ^.. both . folded\n",
"\n",
"quotes :: [(T.Text, T.Text, T.Text)]\n",
"quotes = [(\"Why\", \"So\", \"Serious?\"), (\"This\", \"is\", \"SPARTA\")]\n",
"\n",
"quotes ^.. each\n",
"quotes ^.. each . each\n",
"quotes ^.. each . each . each\n",
"\n",
"-- 3.\n",
"\n",
"[1, 2, 3] ^.. each\n",
"\n",
"(\"Light\" :: String, \"Dark\" :: String) ^.. _1\n",
"\n",
"[(\"Light\", \"Dark\"), (\"Happy\", \"Sad\")] ^.. each . each\n",
"\n",
"[(\"Light\", \"Dark\"), (\"Happy\", \"Sad\")] ^.. each . _1\n",
"\n",
"[(\"Light\", \"Dark\") :: (String, String), (\"Happy\", \"Sad\") :: (String, String)] ^.. each . _2 . each\n",
"\n",
"(\"Bond\", \"James\", \"Bond\") ^.. each"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Custom Folds"
]
},
{
"cell_type": "code",
"execution_count": 62,
"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'>folding :: forall (f1 :: * -> *) (f2 :: * -> *) s a. (Foldable f1, Contravariant f2, Applicative f2) => (s -> f1 a) -> (a -> f2 a) -> s -> f2 s</span>"
],
"text/plain": [
"folding :: forall (f1 :: * -> *) (f2 :: * -> *) s a. (Foldable f1, Contravariant f2, Applicative f2) => (s -> f1 a) -> (a -> f2 a) -> s -> f2 s"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/plain": [
"[Name {getName = \"Grumpy Roger\"},Name {getName = \"Long-John Breeze\"},Name {getName = \"One-eyed jack\"},Name {getName = \"Filthy Frank\"}]"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"newtype Name = Name\n",
" { getName :: String\n",
" } deriving Show\n",
" \n",
"data ShipCrew = ShipCrew\n",
" { _shipName :: Name\n",
" , _captain :: Name\n",
" , _firstMate :: Name\n",
" , _conscripts :: [Name]\n",
" } deriving (Show)\n",
" \n",
"makeLenses ''ShipCrew\n",
"\n",
"-- folding :: Foldable f => (s -> f a) -> Fold s a\n",
":t folding\n",
"\n",
"collectCrewMembers :: ShipCrew -> [Name]\n",
"collectCrewMembers crew =\n",
" [_captain crew, _firstMate crew] ++ _conscripts crew\n",
" \n",
"crewMembers :: Fold ShipCrew Name\n",
"crewMembers = folding collectCrewMembers\n",
"\n",
"myCrew :: ShipCrew\n",
"myCrew =\n",
" ShipCrew\n",
" { _shipName = Name \"Purple Pearl\"\n",
" , _captain = Name \"Grumpy Roger\"\n",
" , _firstMate = Name \"Long-John Breeze\"\n",
" , _conscripts = [Name \"One-eyed jack\", Name \"Filthy Frank\"]\n",
" }\n",
" \n",
"myCrew ^.. crewMembers"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Mapping over folds"
]
},
{
"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'>to :: forall (p :: * -> * -> *) (f :: * -> *) s a. (Profunctor p, Contravariant f) => (s -> a) -> Optic' p f s a</span>"
],
"text/plain": [
"to :: forall (p :: * -> * -> *) (f :: * -> *) s a. (Profunctor p, Contravariant f) => (s -> a) -> Optic' p f s a"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/plain": [
"\"Two-faced Tony\""
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/plain": [
"\"TWO-FACED TONY\""
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/plain": [
"\"TWO-FACED TONY\""
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/plain": [
"[\"Grumpy Roger\",\"Long-John Breeze\",\"One-eyed jack\",\"Filthy Frank\"]"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
":t to\n",
"\n",
"-- Map the end of our fold\n",
"-- to :: (s -> a) -> Fold s a\n",
"\n",
"-- Technically to is actually a Getter rather than a fold, a Getter is just a fold which has this 1-to-1\n",
"-- mapping property, its basically the “getter” half of a lens. A Getter can ALWAYS transform an input\n",
"-- into an output. A pure function s -> a shouldnt ever fail, so we can make this stronger guarantee.\n",
"-- Since were guaranteed an output from to we can use it with view or ^. directly.\n",
"\n",
"Name \"Two-faced Tony\" ^. to getName\n",
"\n",
"Name \"Two-faced Tony\" ^. to getName . to (fmap C.toUpper)\n",
"\n",
"Name \"Two-faced Tony\" ^. to (fmap C.toUpper . getName)\n",
"\n",
"myCrew ^.. crewMembers . to getName"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Combining multiple folds"
]
},
{
"cell_type": "code",
"execution_count": 70,
"metadata": {
"scrolled": true
},
"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'>shipName :: forall (f :: * -> *). Functor f => (Name -> f Name) -> ShipCrew -> f ShipCrew</span>"
],
"text/plain": [
"shipName :: forall (f :: * -> *). Functor f => (Name -> f Name) -> ShipCrew -> f ShipCrew"
]
},
"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'>captain :: forall (f :: * -> *). Functor f => (Name -> f Name) -> ShipCrew -> f ShipCrew</span>"
],
"text/plain": [
"captain :: forall (f :: * -> *). Functor f => (Name -> f Name) -> ShipCrew -> f ShipCrew"
]
},
"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'>firstMate :: forall (f :: * -> *). Functor f => (Name -> f Name) -> ShipCrew -> f ShipCrew</span>"
],
"text/plain": [
"firstMate :: forall (f :: * -> *). Functor f => (Name -> f Name) -> ShipCrew -> f ShipCrew"
]
},
"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'>conscripts :: forall (f :: * -> *). Functor f => ([Name] -> f [Name]) -> ShipCrew -> f ShipCrew</span>"
],
"text/plain": [
"conscripts :: forall (f :: * -> *). Functor f => ([Name] -> f [Name]) -> ShipCrew -> f ShipCrew"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/plain": [
"[\"Grumpy Roger\",\"Long-John Breeze\",\"One-eyed jack\",\"Filthy Frank\"]"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
":t shipName\n",
":t captain\n",
":t firstMate\n",
":t conscripts\n",
"\n",
"crewNames :: Fold ShipCrew Name\n",
"crewNames =\n",
" folding (\\s -> s ^.. captain\n",
" <> s ^.. firstMate\n",
" <> s ^.. conscripts . folded)\n",
" \n",
"myCrew ^.. crewNames . to getName"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Exercises - Custom Folds"
]
},
{
"cell_type": "code",
"execution_count": 100,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"\"YerawizardHarry\""
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/plain": [
"[1,2,4,5]"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/plain": [
"[[1,2],[4,5]]"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/plain": [
"[\"bob\",\"otto\",\"hannah\"]"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/plain": [
"\"cbafed\""
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/plain": [
"[100,200,300,400,500]"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/plain": [
"[1,2]"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/plain": [
"[\"one\",\"two\"]"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/plain": [
"[1,2,3]"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/plain": [
"[2]"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/plain": [
"[1,2,3,4,5,6,7,8]"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/plain": [
"[Left 1,Right 2,Left 3,Right 4]"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/plain": [
"[1,2,3,4,5,6]"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"-- 1.\n",
"\n",
"-- folding :: Foldable f => (s -> f a) -> Fold s a\n",
"-- Map the end of our fold\n",
"-- to :: (s -> a) -> Fold s a\n",
"\n",
"([\"Yer\", \"a\", \"wizard\", \"Harry\"] :: [String]) ^.. folded . each\n",
"-- ([\"Yer\", \"a\", \"wizard\", \"Harry\"] :: [String]) ^.. folded . folded\n",
"\n",
"[[1, 2, 3], [4, 5, 6]] ^.. folded . folding (take 2)\n",
"\n",
"[[1, 2, 3], [4, 5, 6]] ^.. folded . to (take 2)\n",
"\n",
"[\"bob\", \"otto\", \"hannah\"] ^.. folded . to reverse\n",
"\n",
"(\"abc\", \"def\") ^.. folding (\\(a, b) -> [a, b]). to reverse . folded\n",
"\n",
"-- 2.\n",
"\n",
"[1..5] ^.. folded . to (* 100)\n",
"\n",
"(1, 2) ^.. both\n",
"\n",
"[(1, \"one\"), (2, \"two\")] ^.. folded . _2\n",
"\n",
"(Just 1, Just 2, Just 3) ^.. each . _Just\n",
"\n",
"[Left 1, Right 2, Left 3] ^.. each . _Right\n",
"\n",
"[([1, 2], [3, 4]), ([5, 6], [7, 8])] ^.. folded . each . folded\n",
"\n",
"[1, 2, 3, 4] ^.. folded . to (\\x -> if even x then Right x else Left x)\n",
"\n",
"[(1, (2, 3)), (4, (5, 6))] ^.. folded . folding (\\(a, (b, c)) -> [a, b, c])\n",
"\n",
"-- Couldn't think of these last three by myself :( :(\n",
"\n",
"[(Just 1, Left \"one\"), (Nothing, Right 2)] ^.. folded . folding (\\(a, b) -> a ^.. folded <> b ^.. folded)\n",
"\n",
"[(1, \"one\"), (2, \"two\")] ^.. folded . folding (\\(a, b) -> [Left a, Right b])\n",
"\n",
"S.fromList [\"apricots\", \"apples\"] ^.. folded . folding reverse\n",
"\n",
"-- 3. Bonus\n",
"\n",
"-- [(12, 45, 66), (91, 123, 87)] ^.. _\n",
"-- \"54321\"\n",
"\n",
"-- [(1, \"a\"), (2, \"b\"), (3, \"c\"), (4, \"d\")] ^.. _\n",
"-- [\"b\", \"d\"]"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Fold Actions"
]
},
{
"cell_type": "code",
"execution_count": 106,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"True"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/plain": [
"False"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/plain": [
"True"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/plain": [
"False"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/plain": [
"False"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/plain": [
"False"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/plain": [
"Just 2"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/plain": [
"Just 2"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/plain": [
"False"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/plain": [
"True"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/plain": [
"True"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/plain": [
"False"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/plain": [
"4"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/plain": [
"10"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/plain": [
"24"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/plain": [
"Nothing"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/plain": [
"Just 1"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/plain": [
"Just 1"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/plain": [
"Just 1"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/plain": [
"Just 4"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/plain": [
"Just 1"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/plain": [
"Just 4"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/plain": [
"Nothing"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/plain": [
"Nothing"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"elemOf folded 3 [1,2,3,4]\n",
"\n",
"elemOf folded 99 [1,2,3,4]\n",
"\n",
"anyOf folded even [1,2,3,4]\n",
"\n",
"anyOf folded (> 10) [1,2,3,4]\n",
"\n",
"allOf folded even [1,2,3,4]\n",
"\n",
"allOf folded (> 10) [1,2,3,4]\n",
"\n",
"findOf folded even [1, 2, 3, 4]\n",
"\n",
"findOf folded even [1, 2, 3, 4]\n",
"\n",
"has folded []\n",
"\n",
"has folded [1, 2]\n",
"\n",
"hasn't folded []\n",
"\n",
"hasn't folded [1, 2]\n",
"\n",
"lengthOf folded [1, 2, 3, 4]\n",
"\n",
"sumOf folded [1, 2, 3, 4]\n",
"\n",
"productOf folded [1, 2, 3, 4]\n",
"\n",
"firstOf folded []\n",
"\n",
"firstOf folded [1, 2, 3, 4]\n",
"\n",
"preview folded [1, 2, 3, 4]\n",
"\n",
"[1, 2, 3, 4] ^? folded\n",
"\n",
"lastOf folded [1, 2, 3, 4]\n",
"\n",
"minimumOf folded [2, 1, 4, 3]\n",
"\n",
"maximumOf folded [2, 1, 4, 3]\n",
"\n",
"minimumOf folded []\n",
"\n",
"maximumOf folded []"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Queries case study"
]
},
{
"cell_type": "code",
"execution_count": 107,
"metadata": {},
"outputs": [],
"source": [
"data Actor =\n",
" Actor { _name :: String\n",
" , _birthYear :: Int \n",
" } deriving (Show, Eq)\n",
"makeLenses ''Actor\n",
"\n",
"data TVShow =\n",
" TVShow { _title :: String\n",
" , _numEpisodes :: Int\n",
" , _numSeasons :: Int\n",
" , _criticScore :: Double\n",
" , _actors :: [Actor]\n",
" } deriving (Show, Eq)\n",
" \n",
"makeLenses ''TVShow\n",
"\n",
"howIMetYourMother :: TVShow\n",
"howIMetYourMother = TVShow\n",
" { _title = \"How I Met your mother\"\n",
" , _numEpisodes = 208\n",
" , _numSeasons = 9\n",
" , _criticScore = 83\n",
" , _actors =\n",
" [ Actor \"Josh Radnor\" 1974\n",
" , Actor \"Cobie Smulders\" 1982\n",
" , Actor \"Neil Patrick Harris\" 1973\n",
" , Actor \"Alyson Hannigan\" 1974\n",
" , Actor \"Jason Segel\" 1980\n",
" ]\n",
" }\n",
" \n",
"buffy :: TVShow\n",
"buffy = TVShow\n",
" { _title = \"Buffy the Vampire Slayer\"\n",
" , _numEpisodes = 144\n",
" , _numSeasons = 7\n",
" , _criticScore = 81\n",
" , _actors =\n",
" [ Actor \"Sarah Michelle Gellar\" 1977\n",
" , Actor \"Alysson Hannigan\" 1974\n",
" , Actor \"Nicholas Brendon\" 1971\n",
" , Actor \"David Boreanaz\" 1969\n",
" , Actor \"Anthony Head\" 1954\n",
" ]\n",
" }\n",
" \n",
"tvShows :: [TVShow]\n",
"tvShows = [ howIMetYourMother\n",
" , buffy\n",
" ]"
]
},
{
"cell_type": "code",
"execution_count": 117,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"352"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/plain": [
"Just 83.0"
]
},
"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'>maximumByOf :: forall a s. Getting (Endo (Endo (Maybe a))) s a -> (a -> a -> Ordering) -> s -> Maybe a</span>"
],
"text/plain": [
"maximumByOf :: forall a s. Getting (Endo (Endo (Maybe a))) s a -> (a -> a -> Ordering) -> s -> Maybe a"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/plain": [
"Just \"How I Met your mother\""
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/plain": [
"Just (Actor {_name = \"Anthony Head\", _birthYear = 1954})"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/plain": [
"Just (Actor {_name = \"Anthony Head\", _birthYear = 1954})"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"sumOf (folded . numEpisodes) tvShows\n",
"\n",
"maximumOf (folded . criticScore) tvShows\n",
"\n",
"-- maximumBy :: Foldable t => (a -> a -> Ordering) -> t a -> a\n",
"-- maximumByOf :: Fold s a -> (a -> a -> Ordering) -> s -> Maybe a\n",
"\n",
":t maximumByOf\n",
"\n",
"import Data.Ord (comparing)\n",
"\n",
"_title <$> maximumByOf folded (comparing _criticScore) tvShows\n",
"\n",
"minimumByOf (folded . actors . folded) (comparing _birthYear) tvShows\n",
"\n",
"comparingOf :: Ord a => Lens' s a -> s -> s -> Ordering\n",
"comparingOf l = comparing (view l)\n",
"\n",
"minimumByOf (folded . actors . folded) (comparingOf birthYear) tvShows"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Folding with Effects"
]
},
{
"cell_type": "code",
"execution_count": 121,
"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'>traverseOf_ :: forall (f :: * -> *) r s a. Functor f => Getting (Traversed r f) s a -> (a -> f r) -> s -> f ()</span>"
],
"text/plain": [
"traverseOf_ :: forall (f :: * -> *) r s a. Functor f => Getting (Traversed r f) s a -> (a -> f r) -> s -> f ()"
]
},
"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'>forOf_ :: forall (f :: * -> *) r s a. Functor f => Getting (Traversed r f) s a -> s -> (a -> f r) -> f ()</span>"
],
"text/plain": [
"forOf_ :: forall (f :: * -> *) r s a. Functor f => Getting (Traversed r f) s a -> s -> (a -> f r) -> f ()"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/plain": [
"Josh Radnor: 56\n",
"Cobie Smulders: 48\n",
"Neil Patrick Harris: 57\n",
"Alyson Hannigan: 56\n",
"Jason Segel: 50\n",
"Sarah Michelle Gellar: 53\n",
"Alysson Hannigan: 56\n",
"Nicholas Brendon: 59\n",
"David Boreanaz: 61\n",
"Anthony Head: 76"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"-- traverse_ :: (Foldable t, Applicative f) => (a -> f b) -> t a -> f ()\n",
"-- for_ :: (Foldable t, Applicative f) => t a -> (a -> f b) -> f ()\n",
"\n",
":t traverseOf_\n",
":t forOf_\n",
"\n",
"-- traverseOf_ :: Functor f => Fold s a -> (a -> f r) -> s -> f ()\n",
"-- forOf_ :: Functor f => Fold s a -> s -> (a -> f r) -> f ()\n",
"\n",
"calcAge :: Actor -> Int\n",
"calcAge actor = 2030 - _birthYear actor\n",
"\n",
"showActor :: Actor -> String\n",
"showActor actor = _name actor <> \": \" <> show (calcAge actor)\n",
"\n",
"traverseOf_ (folded . actors . folded . to showActor) putStrLn tvShows"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Combining fold results"
]
},
{
"cell_type": "code",
"execution_count": 131,
"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'>foldOf :: forall a s. Getting a s a -> s -> a</span>"
],
"text/plain": [
"foldOf :: forall a s. Getting a s a -> s -> a"
]
},
"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'>foldMapOf :: forall r s a. Getting r s a -> (a -> r) -> s -> r</span>"
],
"text/plain": [
"foldMapOf :: forall r s a. Getting r s a -> (a -> r) -> s -> r"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/plain": [
"(Sum {getSum = 10},Sum {getSum = 572})"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/plain": [
"57.2"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/plain": [
"57.2"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"-- foldOf :: Monoid a => Fold s a -> s -> a\n",
"-- foldMapOf :: Monoid r => Fold s a -> (a -> r) -> s -> r\n",
"\n",
":t foldOf\n",
":t foldMapOf\n",
"\n",
"import Data.Monoid\n",
"\n",
"ageSummary :: Actor -> (Sum Int, Sum Int)\n",
"ageSummary actor = (Sum 1, Sum (calcAge actor))\n",
"\n",
"computeAverage :: (Sum Int, Sum Int) -> Double\n",
"computeAverage (Sum count, Sum total) = fromIntegral total / fromIntegral count\n",
"\n",
"foldOf (folded . actors . folded . to ageSummary) tvShows\n",
"computeAverage $ foldOf (folded . actors . folded . to ageSummary) tvShows\n",
"\n",
"computeAverage $ foldMapOf (folded . actors . folded) ageSummary tvShows"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Using view on folds"
]
},
{
"cell_type": "code",
"execution_count": 135,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"\"do it\""
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/plain": [
"\"do it\""
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/plain": [
"\"\""
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/plain": [
"\"onetwothree\""
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"Just \"do it\" ^. folded\n",
"\n",
"-- Just (42 :: Int) ^. folded\n",
"\n",
"-- When there's a single focus, we just return it\n",
"Just \"do it\" ^. folded\n",
"\n",
"-- When there aren't any focuses, return 'mempty'\n",
"Nothing ^. folded :: String\n",
"\n",
"-- When there are multiple focuses, combine them with (<>).\n",
"(\"one\", \"two\", \"three\") ^. each\n",
"\n",
"-- If we want to fold all focusses together, use foldOf"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Customizing monoidal folds"
]
},
{
"cell_type": "code",
"execution_count": 137,
"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'>foldByOf :: forall s a. Fold s a -> (a -> a -> a) -> a -> s -> a</span>"
],
"text/plain": [
"foldByOf :: forall s a. Fold s a -> (a -> a -> a) -> a -> s -> a"
]
},
"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'>foldMapByOf :: forall s a r. Fold s a -> (r -> r -> r) -> r -> (a -> r) -> s -> r</span>"
],
"text/plain": [
"foldMapByOf :: forall s a r. Fold s a -> (r -> r -> r) -> r -> (a -> r) -> s -> r"
]
},
"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'>foldrOf :: forall r s a. Getting (Endo r) s a -> (a -> r -> r) -> r -> s -> r</span>"
],
"text/plain": [
"foldrOf :: forall r s a. Getting (Endo r) s a -> (a -> r -> r) -> r -> s -> r"
]
},
"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'>foldlOf :: forall r s a. Getting (Dual (Endo r)) s a -> (r -> a -> r) -> r -> s -> r</span>"
],
"text/plain": [
"foldlOf :: forall r s a. Getting (Dual (Endo r)) s a -> (r -> a -> r) -> r -> s -> r"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/plain": [
"fromList [(\"Alyson Hannigan\",1),(\"Alysson Hannigan\",1),(\"Anthony Head\",1),(\"Cobie Smulders\",1),(\"David Boreanaz\",1),(\"Jason Segel\",1),(\"Josh Radnor\",1),(\"Neil Patrick Harris\",1),(\"Nicholas Brendon\",1),(\"Sarah Michelle Gellar\",1)]"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
":t foldByOf\n",
":t foldMapByOf\n",
":t foldrOf\n",
":t foldlOf\n",
"\n",
"foldMapByOf\n",
" (folded . actors . folded . name) -- Focus each actor's name\n",
" (M.unionWith (+)) -- Combine duplicate keys with addition\n",
" mempty -- start with the empty Map\n",
" (\\n -> M.singleton n 1) -- inject names into Maps with a count of 1\n",
" tvShows"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Exercises - Fold Actions"
]
},
{
"cell_type": "code",
"execution_count": 168,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"False"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/plain": [
"\"YoAdrian\""
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/plain": [
"True"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/plain": [
"Just 2"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/plain": [
"Just 11"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/plain": [
"True"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/plain": [
"Just 22"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/plain": [
"Just \"racecar\""
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/plain": [
"True"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/plain": [
"Just (3,\"Be\")"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/plain": [
"3"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/plain": [
"Just \"there\""
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/plain": [
"\"cba\""
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/plain": [
"\"54321\""
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/plain": [
"[\"b\",\"d\"]"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"-- elemOf :: Eq a => Fold s a -> a -> s -> Bool\n",
"-- has :: Fold s a -> s -> Bool\n",
"-- lengthOf :: Fold s a -> s -> Int\n",
"-- sumOf :: Num n => Fold s n -> s -> n\n",
"-- productOf:: Num n => Fold s n -> s -> n\n",
"-- foldOf :: Monoid a => Fold s a -> s -> a\n",
"-- preview :: Fold s a => s -> Maybe a\n",
"-- lastOf :: Fold s a => s -> Maybe a\n",
"-- minimumOf:: Ord a => Fold s a -> s -> Maybe a\n",
"-- maximumOf:: Ord a => Fold s a -> s -> Maybe a\n",
"-- anyOf :: Fold s a -> (a -> Bool) -> s -> Bool\n",
"-- allOf :: Fold s a -> (a -> Bool) -> s -> Bool\n",
"-- findOf :: Fold s a -> (a -> Bool) -> s -> Maybe a\n",
"-- foldrOf :: Fold s a -> (a -> r -> r) -> r -> s -> r\n",
"-- foldMapOf:: Monoid r => Fold s a -> (a -> r) -> s -> r\n",
"\n",
"-- 1.\n",
"\n",
"has folded []\n",
"\n",
"foldOf both (\"Yo\", \"Adrian\")\n",
"\n",
"elemOf each \"phone\" (\"E.T\", \"phone\", \"home\")\n",
"\n",
"findOf folded even [5,7,2,3,13,17,11]\n",
"\n",
"lastOf folded [5,7,2,3,13,17,11]\n",
"\n",
"anyOf folded ((> 9) . length) [\"Bulbasaur\", \"Charmander\", \"Squirtle\"]\n",
"\n",
"findOf folded even [11, 22, 3, 5, 6]\n",
"\n",
"-- 2.\n",
"\n",
"findOf folded (\\xs -> xs == reverse xs) [\"umbrella\", \"olives\", \"racecar\", \"hammer\"]\n",
"\n",
"allOf each even (2, 4, 6)\n",
"\n",
"import Data.Function\n",
"\n",
"maximumByOf folded (compare `on` fst) [(2, \"I'll\"), (3, \"Be\"), (1, \"Back\")]\n",
"\n",
"getSum $ foldMapOf both Sum (1, 2)\n",
"\n",
"-- 3. Could not solve. Copied :(\n",
"\n",
"maximumByOf (folding words) (compare `on` (length . filter (`elem` \"aeiouy\"))) \"Do or do not, there is no try.\"\n",
"\n",
"foldByOf folded (flip (++)) \"\" [\"a\", \"b\", \"c\"]\n",
"\n",
"[(12, 45, 66), (91, 123, 87)] ^.. folded . _2 . to show . to reverse . folded\n",
"\n",
"[(1, \"a\"), (2, \"b\"), (3, \"c\"), (4, \"d\")] ^.. folded . folding (\\(a, b) -> if (even a) then return b else [])"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Higher Order Folds"
]
},
{
"cell_type": "code",
"execution_count": 194,
"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'>taking :: forall (p :: * -> * -> *) (f :: * -> *) s t a. (Conjoined p, Applicative f) => Int -> Traversing p f s t a a -> Over p f s t a a</span>"
],
"text/plain": [
"taking :: forall (p :: * -> * -> *) (f :: * -> *) s t a. (Conjoined p, Applicative f) => Int -> Traversing p f s t a a -> Over p f s t a a"
]
},
"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'>dropping :: forall (p :: * -> * -> *) (f :: * -> *) s t a. (Conjoined p, Applicative f) => Int -> Over p (Indexing f) s t a a -> Over p f s t a a</span>"
],
"text/plain": [
"dropping :: forall (p :: * -> * -> *) (f :: * -> *) s t a. (Conjoined p, Applicative f) => Int -> Over p (Indexing f) s t a a -> Over p f s t a a"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/plain": [
"[1,2]"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/plain": [
"[3,4]"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/plain": [
"[1,2,10,20,100,200]"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/plain": [
"\"AlbDum\""
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/plain": [
"[1,2]"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/plain": [
"\"Alb\""
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/plain": [
"\"AlbusDumbledore\""
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/plain": [
"[1,2,3,10,20,30]"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/plain": [
"[3,10,20,30,100,200,300]"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/plain": [
"[3,30,300]"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/plain": [
"[100,200,300]"
]
},
"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'>backwards :: forall (p :: * -> * -> *) (q :: * -> * -> *) (f :: * -> *) s t a b. (Profunctor p, Profunctor q) => Optical p q (Backwards f) s t a b -> Optical p q f s t a b</span>"
],
"text/plain": [
"backwards :: forall (p :: * -> * -> *) (q :: * -> * -> *) (f :: * -> *) s t a b. (Profunctor p, Profunctor q) => Optical p q (Backwards f) s t a b -> Optical p q f s t a b"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/plain": [
"[3,2,1]"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/plain": [
"[\"two\",\"one\"]"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/plain": [
"[4,3,2,1]"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/plain": [
"[3,4,1,2]"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/plain": [
"[2,1,4,3]"
]
},
"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'>takingWhile :: forall (p :: * -> * -> *) (f :: * -> *) a s t. (Conjoined p, Applicative f) => (a -> Bool) -> Over p (TakingWhile p f a a) s t a a -> Over p f s t a a</span>"
],
"text/plain": [
"takingWhile :: forall (p :: * -> * -> *) (f :: * -> *) a s t. (Conjoined p, Applicative f) => (a -> Bool) -> Over p (TakingWhile p f a a) s t a a -> Over p f s t a a"
]
},
"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'>droppingWhile :: forall (p :: * -> * -> *) (q :: * -> * -> *) (f :: * -> *) a s t. (Conjoined p, Profunctor q, Applicative f) => (a -> Bool) -> Optical p q (Compose (State Bool) f) s t a a -> Optical p q f s t a a</span>"
],
"text/plain": [
"droppingWhile :: forall (p :: * -> * -> *) (q :: * -> * -> *) (f :: * -> *) a s t. (Conjoined p, Profunctor q, Applicative f) => (a -> Bool) -> Optical p q (Compose (State Bool) f) s t a a -> Optical p q f s t a a"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/plain": [
"[1,2,3,4,5,6,7,8,9]"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/plain": [
"[1,5]"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/plain": [
"[90,91,92,93,94,95,96,97,98,99,100]"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/plain": [
"[15,5,1]"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
":t taking\n",
":t dropping\n",
"\n",
"-- taking :: Int -> Fold s a -> Fold s a \n",
"-- dropping :: Int -> Fold s a -> Fold s a\n",
"\n",
"[1, 2, 3, 4] ^.. taking 2 folded\n",
"\n",
"[1, 2, 3, 4] ^.. dropping 2 folded\n",
"\n",
"[[1, 2, 3], [10, 20, 30], [100, 200, 300]] ^.. folded . taking 2 folded\n",
"\n",
"(\"Albus\" :: String, \"Dumbledore\" :: String) ^.. both . taking 3 folded\n",
"\n",
"[[1, 2, 3], [10, 20, 30], [100, 200, 300]] ^.. taking 2 (folded . folded)\n",
"\n",
"(\"Albus\" :: String, \"Dumbledore\" :: String) ^.. taking 3 (both . folded)\n",
"\n",
"(\"Albus\" :: String, \"Dumbledore\" :: String) ^.. taking 3 both . folded\n",
"\n",
"[[1, 2, 3], [10, 20, 30], [100, 200, 300]] ^.. (taking 2 folded) . folded\n",
"\n",
"-- ([\"Albus\", \"Dumbledore\"], [\"Severus\", \"Snape\"]) ^.. taking 3 (both . folded)\n",
"\n",
"-- ([\"Albus\", \"Dumbledore\"], [\"Severus\", \"Snape\"]) ^.. taking 3 (both . folded) . folded\n",
" \n",
"[[1, 2, 3], [10, 20, 30], [100, 200, 300]] ^.. dropping 2 (folded . folded)\n",
" \n",
"[[1, 2, 3], [10, 20, 30], [100, 200, 300]] ^.. folded . dropping 2 folded\n",
" \n",
"[[1, 2, 3], [10, 20, 30], [100, 200, 300]] ^.. dropping 2 folded . folded\n",
" \n",
"-- (\"Albus\", \"Dumbledore\") ^.. both . dropping 2 folded\n",
" \n",
"-- (\"Albus\", \"Dumbledore\") ^.. dropping 2 (both . folded)\n",
"\n",
"-- backwards :: Fold s a -> Fold s a\n",
"\n",
":t backwards\n",
"\n",
"[1, 2, 3] ^.. backwards folded\n",
"\n",
"(\"one\", \"two\") ^.. backwards both\n",
"\n",
"[(1, 2), (3, 4)] ^.. backwards (folded . both)\n",
"\n",
"[(1, 2), (3, 4)] ^.. backwards folded . both\n",
"\n",
"[(1, 2), (3, 4)] ^.. folded . backwards both\n",
"\n",
"-- takingWhile :: (a -> Bool) -> Fold s a -> Fold s a\n",
"-- droppingWhile :: (a -> Bool) -> Fold s a -> Fold s a\n",
"\n",
":t takingWhile\n",
":t droppingWhile\n",
"\n",
"[1..100] ^.. takingWhile (<10) folded\n",
"\n",
"[1, 5, 15, 5, 1] ^.. takingWhile (<10) folded\n",
"\n",
"[1..100] ^.. droppingWhile (<90) folded\n",
"\n",
"[1, 5, 15, 5, 1] ^.. droppingWhile (<10) folded"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Filtering Folds"
]
},
{
"cell_type": "code",
"execution_count": 5,
"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'>filtered :: forall (p :: * -> * -> *) (f :: * -> *) a. (Choice p, Applicative f) => (a -> Bool) -> Optic' p f a a</span>"
],
"text/plain": [
"filtered :: forall (p :: * -> * -> *) (f :: * -> *) a. (Choice p, Applicative f) => (a -> Bool) -> Optic' p f a a"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/plain": [
"[2,4]"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/plain": [
"[\"passionfruit\",\"pomegranate\"]"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"-- filtered :: (s -> Bool) -> Fold s s\n",
"\n",
":t filtered\n",
"\n",
"[1, 2, 3, 4] ^.. folded . filtered even\n",
"\n",
"[\"apple\", \"passionfruit\", \"orange\", \"pomegranate\"] ^.. folded . filtered ((> 6) . length)\n",
"\n",
"data Card = \n",
" Card { _name :: String\n",
" , _aura :: Aura\n",
" , _holo :: Bool\n",
" , _moves :: [Move]\n",
" } deriving (Show, Eq)\n",
" \n",
"data Aura\n",
" = Wet\n",
" | Hot\n",
" | Spark\n",
" | Leafy\n",
" deriving (Show, Eq)\n",
"\n",
"data Move =\n",
" Move { _moveName :: String\n",
" , _movePower :: Int\n",
" } deriving (Show, Eq)\n",
" \n",
"makeLenses ''Card\n",
"makeLenses ''Move\n",
"\n",
"deck :: [Card]\n",
"deck = [ Card \"Skwortul\" Wet False [Move \"Squirt\" 20]\n",
" , Card \"Scorchander\" Hot False [Move \"Scord\" 20]\n",
" , Card \"Seedasaur\" Leafy False [Move \"Allergize\" 20]\n",
" , Card \"Kapichu\" Spark False [Move \"Poke\" 10, Move \"Zap\" 30]\n",
" , Card \"Elecdude\" Spark False [Move \"Asplode\" 50]\n",
" , Card \"Garydose\" Wet True [Move \"Gary's move\" 40]\n",
" , Card \"Moisteon\" Wet False [Move \"Soggy\" 3]\n",
" , Card \"Grasseon\" Leafy False [Move \"Leaf Cut\" 30]\n",
" , Card \"Spicyeon\" Hot False [Move \"Capsaicisize\" 40]\n",
" , Card \"Sparkeon\" Spark True [Move \"Shock\" 40, Move \"Battery\" 50]\n",
" ]"
]
},
{
"cell_type": "code",
"execution_count": 12,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"3"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/plain": [
"5"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/plain": [
"[\"Elecdude\",\"Sparkeon\"]"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/plain": [
"5"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/plain": [
"[\"Asplode\",\"Shock\",\"Battery\"]"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"lengthOf (folded . aura . filtered (== Spark)) deck\n",
"\n",
"lengthOf (folded . moves . folded . movePower . filtered (> 30)) deck\n",
"\n",
"deck ^.. folded . filtered (anyOf (moves . folded . movePower) (> 40)) . name\n",
"\n",
"lengthOf (folded . filtered ((== Spark) . _aura) . moves . folded) deck\n",
"\n",
"deck ^.. folded . filtered ((== Spark) . _aura) . moves . folded . filtered ((> 30) . _movePower) . moveName "
]
},
{
"cell_type": "code",
"execution_count": 14,
"metadata": {},
"outputs": [],
"source": [
"-- filteredBy requires lens-4.18.0 \n",
"\n",
"-- filteredBy :: Fold s a -> Fold s s\n",
"\n",
"-- filteredBy :: Fold s a -> IndexedTraversal' a s s\n",
"\n",
"-- filteredBy :: (Indexable i p, Applicative f) => Getting (First i) a i -> p a (f a) -> a -> f a"
]
}
],
"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
}