Houjun Liu

SU-CS242 NOV122024

Haskell

functional

We can express lambda calculi

\begin{equation} f = \lambda x . x \qty(\lambda y . y) \end{equation}

def f = \x -> x (\y -> y)

This is currently polymorphic

Haskell primer

pairs!

dup' :: a -> (a,a)
dup' x = (x,x)

arrows here are right associative

pattern match

fst :: (a,b) -> a
fst (x, _) = x
fst (x, _) = x

underscore has special meaning

lists!

a list (cons)

1 : 2

nil

[]

we can also write

[1,2]

ADTs

data IntList = IntCons Int IntList | IntNil

btw; you can also use `backticks` to infix something, so to construct something you can write

12 `IntCons` IntNil

Generic ADTs

data List a = Cons a (List a) | Nil
l :: List String

dot operator

You can compose functions together—

fn =  f1 . f2 . f3

lazy semantics / normal order

Haskell is a normal order language (…caveats, but basically). This makes side-effects (i.e. a case where the return value isn’t used) is hard because side effects don’t actually use the return value so it will never be evaluated.

Some solutions…

  • “impure” languages

    Don’t evaluate normal order, and then have side effects directly.

    • OCaml
    • Scala
    • F#

    this makes side effects easy but prevents normal order evaluation

monads

notice that you can have monads encoded through ADTs

data State s a = State (s -> (s,a))

whereby the State monad takes an old state in, and some new state and return value. But, we now have to write state and bind for each possible monad. So, we can abstract away by wrapping stuff in a monad instance.

To implement: typeclasses!!

A monad is defined already as—

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

we can inherit this type class

instance Monad (State s) where
  return = myReturnFunction
  bind = myBindFunction

now, we can then define functions that check if stuff inherits this typeclass

-- silly monad thing
callBind :: Monad m => (a -> mb) -> m -> m
callBind f m1 m2 = bind m f...

this function is now generic over any monads

other typeclasses

class Applicative m where
  pure :: a -> m a
  app :: m (a -> b) -> m a -> m b

so you write