On Github svalaskevicius / haskell-from-scratch
Sarunas Valaskevicius @ Inviqa
Many examples for desktop include: - xmonad - the famous window manager - pandoc - document converter
Serverside: - yesod - web framework - many companies include some haskell based component in their stacky = f x g = h y y
g = h (f x) (f x)
printN n = putStrLn . (intercalate " ") . (map show) . (take n) print10 = printN 10 print10 [1..]
... or even
fibs :: [Integer] fibs = 1 : 1 : zipWith (+) fibs (tail fibs)
Laziness can be bad too - and space leaks are the effects we want to avoid.
It is possible to specify strict computation when required.
stricter :: Integer -> Integer -> Integer stricter a b = id $! a + b
"If it type-checks, it's most likely good"
countSame :: Eq a => a -> [a] -> Int
destructuring matches
maybePlus :: Int -> Maybe Int -> Maybe Int maybePlus a (Just t) = Just $ t + a maybePlus _ Nothing = Nothing
all functions return either the end result or function to get it:
f :: a -> b -> c
f 3 has type (b -> c), which is a function itself.
directory path is mapped to the module name
Data.List
data MyType = MyIntType Int | MyEmptyType | MyStringType String
Defines a new type MyType and provides three data constructors.
type Deck = [Card]
Defines a type alias. The data can still be accessed using the original type.
newtype Deck = Deck [Card]
A combination of data and type - the usage of the resulting type is that of a data type, however the runtime is of a type alias.
myFunction :: Type myFunction arguments = body
Defines a new function available within the module.
map (\x -> x+5) [1..]
\params -> body - defines a lambda function to use.
fib :: Integer -> Integer fib 0 = 1 fib 1 = 1 fib n = fib (n-1) + fib (n-2)
alg :: [Integer] -> Integer -> Integer alg (x:x':xs) a | x == a = x' + alg xs x' | otherwise = alg (x':xs) x alg [_] _ = 0 alg [] _ = 0
Allows computation in the matching.
alg :: [Integer] -> Integer -> Integer
alg (x:x':xs) a = case x == a of
True -> x' + alg xs x'
_ -> alg (x':xs) x')
alg [_] _ = 0
alg [] _ = 0
Pattern-matches in the code.
alg :: [Integer] -> Integer -> Integer
alg (x:x':xs) a = if x == a then x' + alg xs x'
else alg (x':xs) x'
alg [_] _ = 0
alg [] _ = 0
myFunction :: Int
myFunction = let x = 1
in x + 1
myFunction :: Int
myFunction = increasedX
where x = 1
increasedX = x + 1
myFunction :: IO Int
myFunction = do
other <- otherFunction
return $ 1 + other
myFunction :: IO Int
myFunction = do
let x = 1
return x
main :: IO() main = putStrLn "hello world"
worldType :: IO String
worldType = return "haskell"
main :: IO()
main = do
whatWorld <- worldType
putStrLn $ "hello " ++ whatWorld ++ " world"
Note: indentation matters.
class (Eq a) => Ord a where
compare :: a -> a -> Ordering
(<), (<=), (>), (>=) :: a -> a -> Bool
max, min :: a -> a -> a
compare x y = if x == y then EQ
else if x <= y then LT
else GT
x < y = case compare x y of { LT -> True; _ -> False }
x <= y = case compare x y of { GT -> False; _ -> True }
x > y = case compare x y of { GT -> True; _ -> False }
x >= y = case compare x y of { LT -> False; _ -> True }
max x y = if x <= y then y else x
min x y = if x <= y then x else y
data MyType = MyType Int deriving Eq
instance Ord MyType where
(MyType a) <= (MyType b) = a <= b
(in this case, simply deriving (Eq, Ord) would also have worked)
findLowerThan :: Ord a => a -> [a] -> [a] findLowerThan measure = filter (< measure)
In haskell, it is possible to compose two functions to one using the (.) operator:
foo :: Int -> String foo = show bar :: String -> [String] bar x = [x] foobar = bar . foo foobar 5 -- ["5"]
...it is not a language construct - like many others, it is a simple function, defined in the Prelude:
(.) :: (b -> c) -> (a -> b) -> a -> c (.) f g = \x -> f (g x)
class Monoid a where
mempty :: a
-- ^ Identity of 'mappend'
mappend :: a -> a -> a
-- ^ An associative operation
mconcat :: [a] -> a
mconcat = foldr mappend mempty
Sum 4 <> Sum 3 <> Sum 2 <> Sum 1
-- Sum{getSum = 10}
mconcat . (map Sum) $ [1..4]
-- Sum{getSum = 10}
mconcat . (map $ Just . Sum) $ [1..4]
-- Just (Sum{getSum = 10})
Just (Sum 10) <> Nothing <> Just (Sum 5)
-- Just (Sum{getSum = 15})
Wikipedia: "In mathematics and computer science, a higher-order function is a function that does at least one of the following:
For example, map and fold (reduce) are very common in functional paradigm.
data MyType a = MyType { usedValue :: a }
myFunction :: f a -> f a
definition:
class Functor f where fmap :: (a -> b) -> f a -> f b
numbers = [1..10] strings = fmap show numbers -- ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10"] notSureIfNumber = Just 9 notSureIfString = fmap show notSureIfNumber -- Just "9" notSureIfNumber = Nothing notSureIfString = fmap show notSureIfNumber -- Nothing
it's definition:
class Functor f => Applicative f where
pure :: a -> f a
(<*>) :: f (a -> b) -> f a -> f b
(*>) :: f a -> f b -> f b
(<*) :: f a -> f b -> f a
apply a "boxed" function to a "boxed" value:
Just (+1) <*> Just 1 -- Just 2
apply a binary function:
Just (+) <*> Just 1 <*> Just 4 -- Just 5
Just (+) <*> Just 1 <*> Nothing -- Nothing
a shorthand for fmap:
(+) <$> Just 1 <*> Just 4 -- Just 5
class Monad m where
return :: a -> m a
(>>=) :: m a -> (a -> m b) -> m b
(>>) :: m a -> m b -> m b
m >> k = m >>= \_ -> k
Just 1 >>= (\a -> return $ a+1) -- or just "Just 1 >>= return . (+1)" -- Just 2
The do notation is just syntactic sugar over >>=!
computation :: Maybe Int
computation = do
a <- Just 1
return $ a + 1
echo :: IO () echo = getLine >>= putStrLn
Any questions?