{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "------------------------------------------------------------------------\n", "\n", "Types\n", "=====\n", "\n", "Type annotations\n", "----------------\n", "\n", "- Every expression can be annotated with a *type signature*\n", "- Types can be *generic* and have *type variables*\n", "\n", "Count with type signature\n", "-------------------------" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "label": "Haskell" }, "outputs": [], "source": [ "count' :: [a] -> Int -> Int\n", "count' [] result = result\n", "count' (first:rest) result = count' rest (result + 1)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "count :: [a] -> Int\n", "count list = count' list 0" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "------------------------------------------------------------------------\n", "\n", "Laziness\n", "========\n", "\n", "Nonstrict evaluation\n", "--------------------\n", "\n", "- Expressions are not evaluated until their value is needed\n", "- Haskell implements this using *lazy evaluation*\n", "\n", "------------------------------------------------------------------------\n", "\n", "Laziness\n", "========\n", "\n", "Infinite lists\n", "--------------" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "label": "Haskell" }, "outputs": [], "source": [ "allNumbersStartingAt n = n : allNumbersStartingAt (n+1)\n", "take 5 (allNumbersStartingAt 0)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "``` {.haskell .fragment}\n", "→ [0,1,2,3,4]\n", "```\n", "\n", "Repeat a list endlessly\n", "-----------------------" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "label": "Haskell" }, "outputs": [], "source": [ "take 11 (cycle ['S','O','S', '-'])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "``` {.haskell .fragment}\n", "→ \"SOS-SOS-SOS\"\n", "```\n", "\n", "------------------------------------------------------------------------\n", "\n", "Partial function application\n", "============================\n", "\n", "Infix functions (operators)\n", "---------------------------\n", "\n", "- Can also be partially applied\n", "- Just wrap them in parenthesis and omit one operand\n", "\n", "Example `/`\n", "-----------" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "divideByTen :: Fractional a => a -> a\n", "divideByTen = (/ 10)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Example `elem`\n", "--------------" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "isUpperCase :: Char -> Bool\n", "isUpperCase = (`elem` ['A' .. 'Z'])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "------------------------------------------------------------------------\n", "\n", "Functions as arguments\n", "======================\n", "\n", "Example: Do something twice\n", "---------------------------" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "label": "Haskell" }, "outputs": [], "source": [ "applyTwice :: (a -> a) -> a -> a\n", "applyTwice f x = f (f x)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "- First parameter is a function of type `(a -> a)`\n", "- Second parameter is a value of type `a`\n", "\n", "Things to do twice\n", "------------------" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "label": "Haskell" }, "outputs": [], "source": [ "applyTwice (+3) 10\n", "applyTwice (\"Hello, \" ++) \"who is there?\"\n", "applyTwice (3:) [1]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "------------------------------------------------------------------------\n", "\n", "`zipWith'` implementation\n", "=========================\n", "\n", "Recursive function with pattern matching\n", "----------------------------------------" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "label": "Haskell" }, "outputs": [], "source": [ "zipWith' :: (a -> b -> c) -> [a] -> [b] -> [c]\n", "zipWith' f [] bs = []\n", "zipWith' f as [] = []\n", "zipWith' f (a:as) (b:bs) = f a b : zipWith' f as bs" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "------------------------------------------------------------------------\n", "\n", "`zipWith'` applications\n", "=======================\n", "\n", "Guess what the results are\n", "--------------------------" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "label": "Haskell" }, "outputs": [], "source": [ "zipWith' (+) [1, 2, 3] [1, 2, 3]\n", "zipWith' (*) (replicate 4 3) [1..]\n", "zipWith' max [3,7,2] [4,1,6]\n", "zipWith' (++) [\"James T. \", \"\", \"Nyota \"] [\"Kirk\", \"Spock\", \"Uhura\"]" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "label": "Haskell" }, "outputs": [], "source": [ "fibs = 0 : 1 : zipWith' (+) fibs (tail fibs)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "------------------------------------------------------------------------\n", "\n", "Assignment 1\n", "============\n", "\n", "Fibonacci number\n", "----------------\n", "\n", "- Calculate the Ns number of the Fibonacci sequence\n", "- First hit on Google for *haskell fibonacci*: [The Fibonacci\n", " sequence -\n", " HaskellWiki](https://wiki.haskell.org/The_Fibonacci_sequence)\n", "\n", "Canonical Haskell implementation\n", "--------------------------------" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "label": "Haskell" }, "outputs": [], "source": [ "fibs :: [Integer]\n", "fibs = 0 : 1 : zipWith (+) fibs (tail fibs)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "------------------------------------------------------------------------\n", "\n", "Mapping\n", "=======\n", "\n", "Function `map`\n", "--------------" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "label": "Haskell" }, "outputs": [], "source": [ "map :: (a -> b) -> [a] -> [b] \n", "map _ [] = [] \n", "map f (x:xs) = f x : map f xs " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "- Take a function\n", "- Apply to every element of the list\n", "- Collect the results in a list\n", "\n", "------------------------------------------------------------------------\n", "\n", "Mapping\n", "=======\n", "\n", "Examples\n", "--------" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "label": "Haskell" }, "outputs": [], "source": [ "map (\"Beam me up, \" ++) [\"Kirk\", \"Spock\", \"Scotty\"]\n", "map (replicate 3) [1, 2, 3]\n", "map fst [('A', 'B'), ('C', 'D'), ('E', 'F')]\n", "map snd [('A', 'B'), ('C', 'D'), ('E', 'F')]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "------------------------------------------------------------------------\n", "\n", "Filtering\n", "=========\n", "\n", "Function `filter`\n", "-----------------" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "label": "Haskell" }, "outputs": [], "source": [ "filter' :: (a -> Bool) -> [a] -> [a]\n", "filter' _ [] = []\n", "filter' p (x:xs)\n", " | p x = x : filter' p xs\n", " | otherwise = filter' p xs" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "- Take a *predicate*\n", "- Apply to each element of the list\n", "- Assemble new list of elements that satisfy the predicate\n", "\n", "------------------------------------------------------------------------\n", "\n", "Filtering\n", "=========\n", "\n", "Examples\n", "--------" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "label": "Haskell" }, "outputs": [], "source": [ "filter (>3) [1,5,3,2,1,6,4,3,2,1]\n", "filter even [1,5,3,2,1,6,4,3,2,1]\n", "filter (`elem` ['a'..'z']) \"Beam me up, Scotty!\"\n", "filter (`elem` ['A'..'Z']) \"Beam me up, Scotty!\"" ] } ], "nbformat": 4, "nbformat_minor": 5, "metadata": { "language_info": { "name": "haskell", "file_extension": ".hs", "pygments_lexer": "Haskell", "version": "8.6.5", "codemirror_mode": "ihaskell" }, "kernelspec": { "name": "haskell", "display_name": "Haskell", "language": "haskell" } } }