diff --git a/optics.ipynb b/optics.ipynb new file mode 100644 index 0000000..b6ec27c --- /dev/null +++ b/optics.ipynb @@ -0,0 +1,212 @@ +{ + "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 +}