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?