Monads, Monads Everywhere! – A puzzling journey inside Haskell Republic – Functions



Monads, Monads Everywhere! – A puzzling journey inside Haskell Republic – Functions

0 0


haskell-talk

Haskell talk at H-Farm

On Github chritchens / haskell-talk

Monads, Monads Everywhere!

A puzzling journey inside Haskell Republic

What the hack is Haskell and why should I use it?

Haskell is:

a strongly typed functional programming language

with polimorphic types

based on the simply typed lambda calculus

with automatic type inference and checking

and no side effects

And so?

If it compiles it just works

No side effects means safety

Functional programming allows you to stay high level

enhancing good design patterns by default

and make easy hard things (e.g. Quickcheck, Pandoc, xmonad)

What has been used for?

Embedded languages as Ivory and programmin languages as Idris

Embedded systems as UAVs software

Compilers

Type-safe Web Frameworks as Yesod

Type-safe database management as in Persistent

But no one use it in production!

quite false...

It's used by:

DARPA in two projects: High-Assurance Cyber Military Systems (HACMS) and Clean-slate design of Resilient, Adaptive, Secure Hosts (CRASH) Google in internal projects and published Ganeti, a cluster virtual server management software Facebook for data management (check Haxl) and PHP manipulation (lex-pass) MIRI (Machine Intelligence Research Institute) AT&T for network security many financial institutions (Allston Trading, Tsuru Capital, Deutsche Bank for trading) some startups (Better, MailRank has been acquired by Facebook, Chordify, CircuitHub, Fynder)

Cool, but how you code in Haskell?

Let's start with the basics..

Functions

You define functions like this:

            {-| foo is a function without type signature
                x and y are its variables
                the compiler will rise an exception when
                the function will be invoked with uncomparable
                variables
            -}
            foo x y = if x > y then x else y

            -- bar is a function with type signature
            -- and a safe interface to foo
            bar :: Int -> Int -> Bool
            bar x y = foo x y
            

You bind local variables with `let... in`

              foobar :: Float -> Float -> Float
              foobar x y = 
                let z = cos x 
                in z*x*y 
            

or where

              foobar :: Double -> Double -> Double
              foobar x y = z*x*y
                where
                  z = cos x
            

recursive functions with pattern matching

              fact n =
                | n == 0 = 0
                | otherwise = n * (fact n - 1)
            

Overloaded functions

              map f [] = []
              map f x:xs = f x : map f xs
            

Pattern matching with case

              map f l = case l of
                ([]) -> []
                (x:xs) -> f x : map xs
            

or with guards

              filter p [] = []
              filter p (x:xs) =
                | p y = y : filter p ys
                | otherwise = filter p ys
            

Lambda expressions

              -- takes a variable a and return
              -- the application of f on a
              fun f = \a -> f a
            

Types

You can define different kind of types:

product types are n-uples

              data Phone = Phone Vendor OS
            

sum types are enumerations

              data OS = Android | IOs
            

datatypes are aliased types

              datatype Vendor = String
            

Polymorphic types

              data Maybe a = Just a | Nothing
              data Either a b = Left a | Right b
            

Pattern matching types

              maybeDouble :: (a :: Maybe Numeric) => a -> a
              maybeDouble x =
                | Just k -> Just (k*2)
                | otherwise -> Nothing
            

And now the advanced stuff

Monoids

              class Monoid a where
                -- the identity element
                mempty :: a
                -- the associative operation (+, *, etc)
                mappend :: a -> a -> a

                -- reduce the list of elements of type a
                -- using mappend as operation
                mconcat :: [a] -> a
                -- mconcat = foldl mempty mappend
                mconcat = foldr mappend mempty
            

Laws

Any instance of Monoid have to satisfy these rules:

              -- mempty is the identity element w.r.t mappend
              mempty `mappend` x = x
              x `mappend` mempty = x
              -- mappend is associative
              (x `mappend` y) `mappend` z = x `mappend` (y `mappend` z)
            

              -- lists are monoids
              instance Monoid [a] where
                mempty = []
                mappend = (++)
                mconcat = foldr mappend mempty
            

Functors

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

Laws

              fmap id = id
              -- '.' is function composition and it
              -- works as in mathematics
              fmap (g . h) = (fmap g) . (fmap h)
            

Examples

              instance Functor [] where
                fmap _ [] = []
                -- ':' is the operator for list 
                -- concatenation         
                fmap g (x:xs) = g x : fmap g xs
            

Foldable

              class Foldable t where
                fold :: Monoid m => t m -> m
                foldMap :: Monoid m => (a -> m) -> t a -> m

                foldr :: (a -> b -> b) -> b -> t a -> b
                foldl :: (a -> b -> a) -> a -> t b -> a
                foldr1 :: (a -> a -> a) -> t a -> a
                foldl1 :: (a -> a -> a) -> t a -> a
            

Examples

    instance Foldable [] where
      foldMap g = mconcat . map g

    data Tree a = Empty | Leaf a | Node (Tree a) a (Tree a)

    instance Foldable Tree where
      foldMap f Empty = mempty
      foldMap f (Leaf x) = f x
      foldMap f (Node l k r) = foldMap f l `mappend` f k `mappend` foldMap f r
            

Applicative

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

Laws

              -- identity law
              pure id <*> v = v
              -- homomorphism
              pure f <*> pure x = pure (f x)
              -- interchange
              u <*> pure y = pure ($ y) <*> u
            

Examples

              instance Applicative [] where
                pure x = [x]
                -- array comprehension
                gs <*> xs = [ g x | g <- gs, x <- xs ]
            

Monad

              class Monad m where
                return :: a -> ma
                (>>=)  :: m a -> (a -> m b) -> m b
                (>>)   :: m a -> m b -> m b
                m >> n = m >>= \_ -> n

                fail   :: String -> m a
            

Laws

              return a >>= k = k a
              m >>= return = m
              m >>= (\x -> k x >>= h) = (m >>= k) >>= h

              fmap f xs = xs >>= return . f
            

do notation

The "do { x <- foo; bar x }" is syntactic sugar for "foo >>= \x -> bar"

              f :: (Monad m) => m b
              f = do
                -- x :: b
                -- foo :: m a -> m b
                x <- foo
                -- bar :: b -> m c
                bar x
            

Examples

      instance Monad Maybe where
        -- return :: a -> Maybe a
        return = Just
        -- (>>=) :: Maybe a -> (a -> Maybe b) -> Maybe b
        (Just x) >== g = g x
        Nothing >>= _ = Nothing
        -- m >> n = m >>= \_ -> n
    
      instance Monad IO where
        -- return :: a -> IO a
        return = IO
        -- (>>=) :: IO a -> (a -> IO b) -> IO b
        (IO x) >>== g = g x

      main :: IO ()
      -- putStr :: String -> IO ()
      main = do putStr "What is your name?"
                -- readLn :: Read a => IO a
                -- a is an instance of Read
                -- so it has a method read
                -- to convert it from String
                a <- readLn
                putStr "How old are you?"
                b <- readLn
                -- print :: Show a => a -> IO ()
                -- a is an instance of Show, so
                -- it has a method show to convert
                -- it to String
                print (a, b)

      main2 = putStr "What is your name?"
              >> readLn
              >>= \a -> putStr "How old are you?"
              >> readLn
              >>= \b -> print (a, b)
            

You can *hask* me anything about Haskell from 25pm to 26pm.

That's all folks!