Skip to content

Instantly share code, notes, and snippets.

@ajnsit
Last active May 12, 2018 18:07
Show Gist options
  • Save ajnsit/457c54197979fc40c77e3af513306598 to your computer and use it in GitHub Desktop.
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
-- 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