haskell-notebooks/optics.ipynb

213 lines
5.5 KiB
Text
Raw Normal View History

{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Optics\n",
"\n",
"## What are optics?\n",
"\n",
"Lenses, Folds, Traversals, Prisms and Isos are all types of Optics.\n",
"\n",
"## Strengths\n",
"\n",
"1. Composition\n",
"2. Separation of Concerns\n",
"3. Concision\n",
"4. Enforcing interface boundaries\n",
"5. Principled and mature ecosystem\n",
"\n",
"## Weaknesses\n",
"\n",
"1. Type-errors\n",
"2. Complex Implementation\n",
"3. Vast number of combinators\n",
"\n",
"## Some examples\n"
]
},
{
"cell_type": "code",
"execution_count": 14,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"30"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/plain": [
"[\"This one t...\",\"Nuff said.\",\"This is a ...\"]"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/plain": [
"27"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/plain": [
"\"Why Is A Raven Like A Writing Desk\""
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/plain": [
"(Just 300,Left (\"hello\",[1300,1500,1700]))"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/plain": [
"[1,8,3,6,5,4,7,2]"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/plain": [
"(\"eee\",\"hno\",\"orttw\")"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/plain": [
"[3,0,1,6]"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/plain": [
"What is your name?\n",
"What is your quest?\n",
"What is your favourite color?\n",
"(\"Sir Galahad\",\"To seek the holy grail\",\"Black I think\")"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"-- Required Language Extensions and imports\n",
"\n",
"{-# 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",
"-- Below examples are taken from Chris Penner's Optics by Example\n",
"\n",
"-- View nested fields of some record type\n",
"\n",
"--- view (address . country) person\n",
"---\"Canada\"\n",
"\n",
"-- Update portions of immutable data structures\n",
"\n",
"-- set _3 False ('a', 'b', 'c')\n",
"-- ('a', 'b', False)\n",
"\n",
"-- These selectors compose!\n",
"-- We can perform a task over deeply nested subsets of data.\n",
"-- Let's sum all numbers which in a 'Left' within the right half of each tuple\n",
"\n",
"sumOf (folded . _2 . _Left) [(True, Left 10), (False, Right \"pepporoni\"), (True, Left 20)]\n",
"\n",
"let stories = [\"This one time at band camp\", \"Nuff said.\", \"This is a short story\"]\n",
"\n",
"over (traversed . filtered ((>10) . length)) (\\story -> take 10 story ++ \"...\") stories\n",
"\n",
"-- Summarize a list of numbers, subtracting the 'Left's, adding the 'Right's!\n",
"\n",
"sumOf (folded . beside negated id) [Left 1, Right 10, Left 2, Right 20]\n",
"\n",
"-- Capitalize each word in a sentence\n",
"\"why is a raven like a writing desk\" & worded . _head %~ toUpper\n",
"\n",
"-- Multiply every Integer by 100 no matter where they are in the structure:\n",
"(Just 3, Left (\"hello\", [13, 15, 17])) & biplate *~ 100\n",
"\n",
"-- Reverse the ordering of all even numbers in a sequence.\n",
"-- We leave the odd numbers alone!\n",
"[1, 2, 3, 4, 5, 6, 7, 8] & partsOf (traversed . filtered even) %~ reverse\n",
"\n",
"-- Sort all the characters in all strings, across word boundaries!\n",
"(\"one\", \"two\", \"three\") & partsOf (each . traversed) %~ L.sort\n",
"\n",
"-- Flip the 2nd bit of each number to a 0\n",
"[1, 2, 3, 4] & traversed . bitAt 1 %~ not\n",
"\n",
"-- Prompt the user with each question in a tuple,\n",
"-- then return the tuple with each prompt replaced with the user's input,\n",
"let prompts = ( \"What is your name?\"\n",
" , \"What is your quest?\"\n",
" , \"What is your favourite color?\"\n",
" )\n",
"prompts & each %%~ (\\prompt -> putStrLn prompt >> getLine)"
]
}
],
"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
}