Last active
May 12, 2018 18:07
-
-
Save ajnsit/457c54197979fc40c77e3af513306598 to your computer and use it in GitHub Desktop.
Some code from the absolute beginner's Haskell workshop @ May 2018 ILUGD meetup
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
-- First steps - | |
-- Install Stack tool - haskellstack.org | |
-- Then do - stack setup, and stack ghci. | |
-- Haskell language basics - I | |
-- Conceptually functions are values, values are (no-arg) functions | |
-- The following can be considered a function with no arguments | |
alwaysOne = 1 | |
-- Conceptually, there is no difference between referencing and "running" a function | |
-- Lightweight syntax. Function application is basically whitespace. | |
add 1 2 | |
-- Sum of all numbers from one to ten | |
sum [1..10] | |
-- Note how MUCH simpler that is than the loop method - | |
{- | |
sum = 0 | |
for(i=1;i<=10;i++) { | |
sum += i; | |
} | |
-} | |
-- [...] is inbuilt linked list syntax | |
-- [x..y] means list of numbers from x to y | |
-- Similar to pythonic range(1,10) | |
-- Sum of all prime numbers from 1 to 10 | |
sum (filter isPrime [1..10]) | |
-- OR | |
sum $ filter isPrime [1..10] | |
-- OR for even more readability | |
[1..10] | |
|> filter isPrime | |
|> sum | |
-- Here $ and |> are just function application operators | |
($) f x = f x | |
(|>) x f = f x | |
-- Function to add two numbers | |
-- and the type signature | |
add :: Int -> Int -> Int | |
add x y = x + y | |
-- Functions can have multiple clauses | |
-- Naive Fibonacci | |
-- basically the mathematical definition | |
-- Note the recursion | |
fib 1 = 1 | |
fib 2 = 1 | |
fib n = fib (n-1) + fib (n-2) | |
-- Laziness | |
-- Infinite list of numbers | |
naturals = [1..] | |
-- List of first 10 primes | |
take 10 $ filter isPrime naturals | |
-- Slicing a list | |
-- This returns [6,7,8,9] | |
take 4 $ drop 5 naturals | |
-- Lists in Haskell are really Linked lists | |
-- (:) operator can be thought of as a pointer to the rest of the list | |
(:) :: Int -> [Int] -> [Int] | |
-- Let's define list index (this is O(n)) | |
-- This can also fail at runtime (index out of bounds). | |
-- We will talk about making it safe later. | |
-- This is another example of recursion | |
index 0 (x:_) = x | |
index n (x:xs) = index (n-1) xs | |
-- Memoised fibonacci | |
-- Notice the three way recursion | |
-- Also, it's an example of dynamic programming, as someone pointed out | |
allFibs :: [Int] | |
allFibs = map fib naturals | |
memoFib :: Int -> Int | |
memoFib n = index n allFibs | |
fib :: Int -> Int | |
fib 1 = 1 | |
fib 2 = 1 | |
fib n = memoFib (n-1) + memoFib (n-2) | |
-- Pseudo Quicksort in Haskell (Does not have the same performance characteristics) | |
qsort :: [Int] -> Int | |
qsort [] = [] | |
qsort (x:xs) = qsort (filter (<x) xs) ++ [x] ++ qsort (filter (>=x) xs) | |
-- Algebraic Data types | |
-- Lists must have the same types of elements | |
-- But we can work around that with our own datatypes | |
-- An integer or a string | |
data IntOrString = I Int | S String | |
-- Now we can have a list of strings or integers | |
l :: [IntOrString] | |
l = [I 1, S "Hello", I 2] | |
-- How do we print all strings in this list? | |
-- First we must understand do notation | |
-- Haskell is the world's finest imperative programming language | |
-- Code to ask for a person's name and greet them | |
-- Note that we use indentation to delimit where the steps end | |
do | |
putStrLn "Tell me your name" | |
name <- getLine | |
putStrLn $ "Hello " ++ name | |
-- Function to print all strings in the list | |
-- Note the recursion | |
printAllStrings (S s : ls) = do | |
putStrLn s | |
printAllString ls | |
printAllStrings (_ : ls) = printAllStrings ls | |
printAllStrings [] = return () | |
-- Defining an Integer which could be null | |
data MaybeInt = Just Int | Nothing | |
-- Getting rid of null pointers | |
-- You are forced to handle all cases | |
-- And no errors at runtime | |
add :: MaybeInt -> MaybeInt -> MaybeInt | |
add Nothing Nothing = Nothing | |
add (Just i) Nothing = Just i | |
add Nothing (Just i) = Just i | |
add (Just i) (Just j) = Just (i+j) | |
-- Get the first element of a list of integers | |
head :: [Int] -> Int | |
head [] = 0 -- Forced to think of a default value | |
head (x:_) = x | |
-- Maybe is in the standard lib as - | |
data Maybe a = Just a | Nothing | |
-- Get the first element of a generic list | |
-- Forced to use a Maybe | |
-- There is absolutely no way to write this function otherwise | |
head :: [a] -> Maybe a | |
head [] = Nothing | |
head (x:_) = Just x | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment