On Github chritchens / haskell-talk
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
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)
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
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
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
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
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
class Functor f where
fmap :: (a -> b) -> f a -> f b
fmap id = id
-- '.' is function composition and it
-- works as in mathematics
fmap (g . h) = (fmap g) . (fmap h)
instance Functor [] where
fmap _ [] = []
-- ':' is the operator for list
-- concatenation
fmap g (x:xs) = g x : fmap g xs
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
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
class Functor f => Applicative f where
pure :: a -> f a
(<*>) :: f (a -> b) -> f a -> f b
-- identity law
pure id <*> v = v
-- homomorphism
pure f <*> pure x = pure (f x)
-- interchange
u <*> pure y = pure ($ y) <*> u
instance Applicative [] where
pure x = [x]
-- array comprehension
gs <*> xs = [ g x | g <- gs, x <- xs ]
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
return a >>= k = k a
m >>= return = m
m >>= (\x -> k x >>= h) = (m >>= k) >>= h
fmap f xs = xs >>= return . f
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
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.