UP | HOME

Haskell (pure and lazy, yet functional)

Table of Contents

1 Quick overview

1.1 History and stuff

1.1.1 Unification of efforts in lazy functional programming

1.1.2 A lot of theory underneath

1.1.3 Academy driven, cutting edge research

1.1.4 Evolving standard

1.1.5 Glasgow Haskell Compiler being the canonical implementation

1.1.6 Avoid Success at All Costs

\pause

1.1.7 Hoare quote   B_quote

I fear that Haskell is doomed to succeed.

– C.A.R. Hoare

1.2 Theoretical base

1.2.1 (Typed) λ -calculus

1.2.2 Category theory

1.2.3 Hindley-Milner(-Damas) type inference

1.3 Technical merits

1.3.1 Purely functional

1.3.2 Lazy (non-strict)

1.3.3 Polymorphic strong static typing

\pause

1.3.4 Elegant (sort of), math inspired syntax

2 The language from bird's-eye

2.1 Pure functional?

2.1.1 Program is a tree of nested expresions

2.1.2 Functions are the base building unit

2.1.3 No side effects by default

  1. like in mathematic functions

2.2 Functions

2.2.1 Pattern matching

map :: (a -> b) -> [a] -> [b]
map _ [] = []
map f (x:xs) = f x : map f xs

2.2.2 Curring

  1. Function of N arguments is actually an application of N 1-argument functions
    map (5 +) [1..10]
    

2.2.3 Composition

map (negate . sum . tail) [[1..5],[3..6],[1..7]]

2.3 Lazy?

2.3.1 Evaluation order

2.3.2 Thunks

  1. Delayed computations

    \begin{lstlisting}[language=c++] int* take(int amount, int collection[]) {…} #+ENDSRC

  2. Don't compute anything until/unless required
    take 10 $ map (5 +) [1..]
    

2.4 Strong static typing?

2.4.1 Each expression has a type known at compile time

  1. so do functions

2.4.2 Our types determine a theorem and compiling is a proof of its correctness within the Haskell world

  1. common theme for such advanced type systems

2.4.3 Polymorphic types

Prelude> :t filter

filter :: (a -> Bool) -> [a] -> [a]

2.5 Algebraic data types

2.5.1 Union of possible values or value constructors

data Bool = False | True

data Car = Car {model :: String
	       , year :: Int
	       , burnTime :: Int
	       } deriving (Show)

2.5.2 Type parameters

data Maybe a = Nothing | Just a

data Tree a = EmptyTree | Node a (Tree a)
			  (Tree a)
	    deriving (Show, Read, Eq)

2.6 Typeclasses

2.6.1 Interfaces sort of

2.6.2 If it quacks like a duck, it's a duck

class Eq a where
    (==) :: a -> a -> Bool
    (/=) :: a -> a -> Bool
    x == y = not (x /= y)
    x /= y = not (x == y)

instance (Eq m) => Eq (Maybe m) where

    Just x == Just y = x == y
    Nothing == Nothing = True
    _ == _ = False

2.7 I/O vs Purity

2.7.1 The IO Monad

2.7.2 Reverse words

main = do
    line <- getLine
    if null line
	then return ()
	else do
	    putStrLn $ reverseWords line
	    main

reverseWords :: String -> String
reverseWords = unwords . map reverse . words

2.7.3 Cool one-liner

main = interact $ unlines .
       filter ((>200) . length) . lines

2.8 Functors

2.8.1 Don't confuse with C++ ;-)

2.8.2 Iterable?

2.8.3 Lift ordinary function to operate on boxed value

class Functor f where
    fmap :: (a -> b) -> f a -> f b

instance Functor [] where
    fmap = map

instance Functor Maybe where
    fmap f (Just x) = Just (f x)
    fmap f Nothing = Nothing

2.9 Applicative

2.9.1 Beefed up functors

2.9.2 Sequence of several boxed actions

class (Functor f) => Applicative f where
    pure :: a -> f a
    (<*>) :: f (a -> b) -> f a -> f b

instance Applicative Maybe where
    pure = Just
    Nothing <*> _ = Nothing
    (Just f) <*> something = fmap f something

2.9.3 pure f <*> x ≡ fmap f x

2.10 Monoids

2.10.1 Associative binary function + identity value

2.10.2 Accumulate a boxed value from several boxes

class Monoid m where
    mempty :: m
    mappend :: m -> m -> m
    mconcat :: [m] -> m
    mconcat = foldr mappend mempty

instance Monoid [a] where
    mempty = []
    mappend = (++)

2.11 Monads

2.11.1 Beefed up applicatives

class Monad m where
    return :: a -> m a
    (>>=) :: m a -> (a -> m b) -> m b

    (>>) :: m a -> m b -> m b
    x >> y = x >>= \_ -> y

    fail :: String -> m a
    fail msg = error msg

instance Monad Maybe where
    return x = Just x
    Nothing >>= f = Nothing
    Just x >>= f  = f x
    fail _ = Nothing

3 Pros and cons

3.1 Benefits

3.1.1 The pervasive type system gives a lot of information to the compiler

  1. many types (pun intended) of bugs are prevented at compile time
  2. much room for automatic optimizations
    1. Data Parallel Haskell
  3. secure and formally verifiable programs

3.1.2 Side effects are not the norm and are explicitly specified and controlled

  1. easier to reason about
  2. better concurrency state
    1. how many languages have a working STM implementation?

3.2 Problems

3.2.1 There are cases where static typing may not be natural

3.2.2 For huge systems, you may paint yourself in the corner if having somehow wrong base

3.2.3 Laziness makes order of evaluation non-obvious

  1. trouble with performance bottlenecks identification
  2. memory spikes

4 Resources

5 Fun

5.1 Why so serious?

newline.jpg

Author: Andrey Kotlarski

Created: 2018-07-30 пн 05:04

Emacs 26.1 (Org mode 9.1.9)

Validate