Week 1 Lecture 1
Introduction
There’s a break during the lecture!!!!!
Assignments:
- Six weekly assignments
- 2-3 student groups
- 0-4 points per assignment
- NO RESUBMISSION
Requirements:
- In total, at least 12 points
- At least 1 point per assignment
- only one person has to hand in the assignment form the group
Exam:
Theoretical exam where we have no access to the internet
- 4 hour
- Will be given questions about code written during the course
- Similar questions as we are asked during the assignments
- Exam will be on a computer (ITX)
- AI Assistance is allowed during the course
THE REAL CONTENTS OF THE COURSE
Course in emacs
main :: IO ()
main = putStrLn "Hello World!"double x = x * 2
-- Not well written *enough*. We require them to have type annotations:t double -> double :: Int -> Int
double :: Int -> Int
double x = x * 2
data List a
= Nil
| Cons a (List a)
-- deriving (Eq, Show)
-- `undefined` can be used if you don't know the value yet
-- can be any type, but evaluating it causes a runtime error
-- listLength :: List -> Int
-- listLength l = undefined
listLength :: List a -> Int
-- listLength Nil = 0
-- listLength Cons _ xs = 1 + listLength xs
listLength l =
case l of
Nil -> 0
Cons _ xs -> 1 + listLength xs
-- If we were to try printing one of our lists:
-- • No instance for ‘Show List’ arising from a use of ‘print’
-- There are instances for similar types:
-- instance Show a => Show [a]
-- -- Defined in ‘ghc-internal-9.1002.0:GHC.Internal.Show’
-- `Show` is a typeclass defined by Haskell for turning values into text
-- ghci> :i Show
-- type Show :: * -> Constraint
-- class Show a where
-- showsPrec :: Int -> a -> ShowS
-- show :: a -> String
-- showList :: [a] -> ShowS
-- {-# MINIMAL showsPrec | show #-}
instance Show a => Show (List a) where
-- show :: List a -> String
show Nil = "()"
show (Cons x xs) = show x ++ " " ++ show xs
-- If you do something like `Cons 2 (Cons 1 Nil)`
-- you might get a warning. This is because Haskell has to choose a type for `2` and `1`
-- you can remove this warning with:
-- :set -Wno-type-defaults
element :: (Eq a) => a -> List a -> Bool
element _ Nil = False
element a (Cons x xs) = if x == a
then True
else element a xs
-- typeclasses must apply some rules, that the machine can't check
-- Eq relation requires:
-- 1. reflexivity ( x == x )
-- 2. transitivity ( (x == y && y == z) => x == z )
-- 3. symmetry ( `x == y => y == x )
-- 4. extensionality ( x == y => f x == f y )
instance (Eq a) => Eq (List a) where
(==) Nil Nil = True
(==) Nil (Cons _ _) = False
(==) (Cons _ _) Nil = False
(==) (Cons x xs) (Cons y ys) = if x == y
then xs == ys
else False
-- derives can be used to automatically generate some type class instances
-- like:
{-
data List a
= Nil
| Cons a (List a)
deriving (Show, Eq)
-}
someMass :: Double
someMass = 5
someVelocity :: Double
someVelocity = 9.82
energy :: Double -> Double -> Double
energy mass velocity = mass * (velocity * velocity) / 2
-- energy someVelocity someMass
-- allowed in the current definition (can be messed up p quickly)
-- A somewhat better approach is to define custom data types to enforce the correctness at compile time
data Kg = Kg Double
newtype MetersPerSec = MpS Double
data Joules = J Double
-- :godoh:
instance Num Kg where
Kg x + Kg y = Kg (x + y)
Kg x * Kg y = Kg (x * y)
negate (Kg x) = Kg (-x)
abs (Kg x) = abs (Kg x)
signum (Kg x)= Kg (signum x)
fromInteger i= Kg (fromInteger i)
someMass2 :: Kg
someMass2 = Kg 5
someVelocity2 :: MetersPerSec
someVelocity2 = MpS 9.82
energy2 :: Kg -> MetersPerSec -> Joules
energy2 (Kg mass) (MpS velocity) = J (mass * (velocity * velocity) / 2)
-- Next approach to wrap it smort
-- Represents a quantity
data Q u = Q Double deriving (Show)
-- u is a phantom type. It is not actually used in the definition, but it can be used to impose type restrictions
--data Kilogram = Kilogram
data Kg2 -- no need to allow the construction of the type. Uninhabited type
data MpS2
data J2
instance Num (Q u) where
Q x + Q y = Q (x + y)
Q x * Q y = Q (x * y)
negate (Q x) = Q (-x)
abs (Q x) = abs (Q x)
signum (Q x) = Q (signum x)
fromInteger i = Q (fromInteger i)
-- Quantity of Kilograms
someMass3 :: Q Kg2
someMass3 = Q 5
someVelocity3 :: Q MpS2
someVelocity3 = Q 123
energy3 :: Q Kg2 -> Q MpS2 -> Q J2
energy3 (Q m) (Q v) = Q (m * (v*v)/2)
result = energy3 someMass3 someVelocity3
-- Some more useful standard Haskell techniques:
{- Remember this guy:
element :: (Eq a) => a -> List a -> Bool
element _ Nil = False
element a (Cons x xs) = if x == a
then True
else element a xs
-}
lookupElement :: Eq a => a -> List a -> Maybe a
lookupElement _ Nil = Nothing
lookupElement x (Cons y ys) =
if x == y
then Just y -- ... or x
else lookupElement x ys
mapList :: (a -> b) -> List a -> List b
mapList f Nil = Nil
mapList f (Cons x xs) = Cons (f x) (mapList f xs)
-- fmap is a more generic version of this mapList
-- it works for any type F that allows converting a function `(a -> b)` to a function `(F a -> F b)`
-- such F types are in the Functor typeclass
instance Functor List where
fmap _ Nil = Nil
fmap f (Cons x xs) = Cons (f x) (fmap f xs)
-- Similarly to Functors, there are Foldables. They allow accumulating some data into a single value
instance Foldable List where
-- foldl _ acc Nil = acc
-- foldl f acc (Cons x xs) = foldl f (f acc x) xs
-- foldr is one of the minimal functions you can use
-- foldr :: (a -> b -> b) -> b -> t a -> b
foldr _ acc Nil = acc
foldr f acc (Cons x xs) = f x (foldr f acc xs )