e.g. output = input + 1
Sounds familiar?
f :: Integer -> Integer
f x = x + 1
add :: Integer -> Integer -> Integer
add x y = x + y
add :: Integer, Integer -> Integer
add x y = x + y
add :: Integer -> Integer -> Integer
add x y = x + y
-- We can use add like so:
add 1 2 -- output: 3
-- But also like this:
(add 1) 2 -- output: 3
-- The type of (add 1) is: Integer -> Integer
f : Integer -> Integer
f = add 1
-- Instead of f x = x + 1Given \(add(x,y) = x + y\), what does \(add(x)\) mean?
"Currying"
2 :: Integer
3.14 :: Float
'a' :: Char
[0, 1, 2, 3, 4, 5] :: [Integer]
['D', 'a', 'a', 'n'] :: [Char]
type String = [Char] -- Defines alias
"Hello, Confluente!" :: String
data Degree -- Defines a new data type
= Bachelor
| Master
| PhD
data Person -- Defines a new record type
= Person {
name :: String,
age :: Integer,
degree :: Degree
}
-- Use like this:
Person {
name = "Daan de Graaf",
age = 19,
degree = Bachelor
} :: Person
-- This automatically defines:
name :: Person -> String
age :: Person -> Integer
degree :: Person -> Degree-- Container that may or may not be empty
data Maybe a
= Just a
| Nothing
-- Use like this:
Just 3 :: Maybe Integer
Nothing :: Maybe Integer
-- Useful when return value is undefined for some input
sqrt :: Float -> Float
sqrt 9 -- 3
sqrt -1 -- ?
-- Better:
sqrt :: Float -> Maybe Float
sqrt 9 -- Just 3
sqrt -1 -- Nothingtype Grade = Float
data Course
= Course {
id :: Integer,
name :: String,
grade :: Maybe Grade
}type Average = Floattransform :: [Course] -> Average
-- We need to implement this function[Course]
[Maybe Grade]
[Grade]
Float
Integer
Average
-- Easy for a single Course:
grade :: Course -> Maybe Grade
-- But we need:
grades :: [Course] -> [Maybe Grade]
-- For different apps we also need:
ids :: [Course] -> [Integer]
names :: [Course] -> [String]
-- General pattern?map :: (a -> b) -> [a] -> [b]
-- Substitute Course for a, Maybe Grade for b
map :: (Course -> Maybe Grade) -> [Course] -> [Maybe Grade]
grades :: [Course] -> [Maybe Grade]
grades = map grade-- We need:
magic :: [Maybe Grade] -> [Grade]Extracting 'Just' from a list is a common pattern
catMaybes :: [Maybe Grade] -> [Grade]mapMaybe :: (a -> Maybe b) -> [a] -> [b]
mapMaybe grade :: [Course] -> [Grade]type Average = Float
sum :: [Float] -> Float
length :: [a] -> Integer
(/) :: Float -> Float -> Float
average :: [Grade] -> Average
-- This does not work:
average gs = sum gs / length gs-- Luckily we have:
genericLength :: [a] -> Float
-- This works:
average gs = sum gs / genericLength gs-- Our end goal
transform :: [Course] -> Average
-- We have:
grade :: Course -> Maybe Grade
mapMaybe :: (a -> Maybe b) -> [a] -> [b]
average :: [Grade] -> Averagetransform cs = average . (mapMaybe grade) cs
transform = average . mapMaybe gradetransform cs = average (mapMaybe grade cs)How do we get input to transform?
How do we display transformed output?
-- Haskell evaluates this function at startup
main :: IO ()
main = ...IO ()
IO a?
-- Executing this will yield String
getLine :: IO String
-- Takes a string, yield nothing
putStrLn :: String -> IO ()
-- Example program:
main :: IO ()
main = putStrLn "Hello, world!"do
IO a
a -> IO ()
do notation to construct a pipeline:getLines :: IO [String]
reverse :: [a] -> [a]
putStrLns :: [String] -> IO ()
main :: IO ()
main = do
lines <- getLines -- Pipe creation
let reversed = map reverse lines -- Transformation
putStrLns reversed -- Pipe drainingMonad
do
getCourses :: IO [Course]
transform :: [Course] -> Average
print :: Average -> IO ()
main :: IO ()
main = do
courses <- getCourses -- Pipe creation
let avg = transform courses -- Transformation
print avg -- Pipe draining