- Top 10 IRC channel: #haskell
- Reddit: > 10k subscribers
- Stack Overflow: > 10k questions
- Learn from smarter people.
PURE functional. NO side effects. Everything returns, should be deterministic.
Life isn't deterministic. This is why people think it's not useful.
- Side effects in IO
- Pure everywhere else
Drawn from, return (opposites)
main :: IO ()
main = do
putStrLn "quit the program? y/n"
ans <- getLine
if ans /= "y" then do
putStrLn "not quitting"
main
else return ()
-- or
when (ans /= "y") $ do
putStrLn "not quitting"
main
We'll have:
- Parsing
- DB
- WS Server
- Solver
Next slides are from this excellent tutorial.
Applying functions now depends on context:
data Maybe a = Just a | Nothing
fmap (+3) (Just 2)
Functor is a typeclass:
Functor is just a data type that defines fmap for itself:
So we can:
instance Functor Maybe where
fmap func (Just val) = Just (func val)
fmap func Nothing = Nothing
fmap (+3) (Just 2)
Behind the scenes of fmap (+3) (Just 2)
we get:
Try to apply (+3)
to Nothing
and you get:
ghci>fmap (+3) Nothing
Nothing
Nil is often used as bottom as well as status.
In Haskell we still have bottom: undefined
.
Because bottom subsumes non-termination, the function
isUndefined
would have to solve the halting problem and thus cannot exist.
post = Post.find_by_id(1)
if post
return post.title
else
return nil
end
fmap (getPostTitle) (findPost 1)
--- or with infix
getPostTitle <$> (findPost 1)
Because:
instance Functor [] where
fmap = map
Normal:
fmap (+3) (*2)
instance Functor ((->) r) where
fmap f g = f . g
As a functor, it's function composition! As a monad:
instance Applicative ((->) r) where
-- pure :: a -> r -> a
pure = const
-- (<*>) :: (r -> a -> b) -> (r -> a) -> r -> b
(<*>) g f r = g r (f r)
instance Monad ((->) r) where
-- return :: a -> r -> a
return = const
-- (>>=) :: (r -> a) -> (a -> r -> b) -> r -> b
(>>=) x y z = y (x z) z
Both are wrapped in contexts!
Just 2
Just (+3)
ghci>Just (+2) <*> Just 5
From base:
instance Functor [] where
fmap = map
instance Applicative [] where
pure x = [x]
fs <*> xs = [f x | f <- fs, x <- xs]
xs *> ys = [y | _ <- xs, y <- ys]
instance Monad [] where
xs >>= f = [y | x <- xs, y <- f x]
(>>) = (*>)
return x = [x]
fail _ = []
-- So... what is this?
[(*2),(+3)] <*> [1, 2, 3]
. . .
Apply function that takes 2 args to 2 wrapped values!
ghci>(+) <$> (Just 5)
Just (+5)
ghci>Just (+5) <$> Just 4
ERRRRR
. . .
-- Applicative
ghci>(+) <$> Just 5 <*> Just 4
Just 9
ghci>liftA2 (*) (Just 5) (Just 3)
Just 15