data Bool = False | True
data Point = Point Float Float
let x = Point 3.0 4.0 :: Point
data Shape = Circle Point Float
data Shape = Circle Point Float | Rectangle Point Point
ghci> :t Point
Point :: Float -> Float -> Point
Constructors can be partially applied
ghci> let points = map (Point 0) [1 2 3]
Why doesn’t this work?
Prelude> map (Point 1) [0, 2, 3]
:7:1:
No instance for (Show Point) arising from a use of `print'
Possible fix: add an instance declaration for (Show Point)
In a stmt of an interactive GHCi command: print it
deriving
keyword used to give typeclasses to datatypes
data Point = Point Float Float deriving (Show)
How do we compute the area of a Shape?
area :: Shape -> Float
area s = ...
Pattern matching to the rescue!
area :: Shape -> Float
area (Circle center radius) = pi * r ^ 2
area (Rectangle (Point x1 y1) (Point x2 y2)) = (abs $ x2 - x1) * (abs $ y2 - y1)
myFavoriteShape :: Shape
...
doILikeCircles =
case myFavoriteShape of
Circle _ _ -> True
Rectangle _ _ -> False
data Person = Person String String String String Int Float
age :: Person -> Int
age (Person _ _ _ _ a _) = a
Oh hell no. This is bad.
ghci> data Person = Person {
firstName :: String,
lastName :: String,
phoneNumber :: String,
emailAddress :: String,
age :: Int,
height :: Float
} deriving (Show)
ghci> let chuck = Person {
firstName = "Chuck",
lastName = "Norris",
phoneNumber = "(123) 456-7890",
emailAddress = "chuck@norr.is",
age = -5,
height = 200
}
ghci> height chuck
200
data Tree = EmptyTree | Node Int Tree Tree
Instead of defining a type, we define a Type constructor
data Tree a = EmptyTree | Node a (Tree a) (Tree a)
One caveat:
Tree
is NOT a type, it is a
type constructor
This is an invalid type declaration
insert :: a -> Tree -> Tree
This is correct
insert :: a -> Tree a -> Tree a
data List a = Nil | Cons a (List a)
Nil => []
Cons x xs => (x:xs)
Cons x Nil => [x]
getLine
and
putStrLn
?
If we try to declare
getLine :: String
it must always return the same string
This is not what we want
If we try to declare
putStrLn :: String -> ()
it is not referentially transparent as it has a side effect
greet :: IO ()
greet = do
putStr "What is your name? "
name <- getLine
putStrLn $ "Hi " ++ name ++ "!"
return ()
It’s a () wrapped in an IO
It’s a String wrapped in an IO
This may be a bit more useful
greet :: IO String
greet = do
putStr "What is your name? "
name <- getLine
putStrLn $ "Hi " ++ name ++ "!"
return name
return
in Haskell is unlike any other return you have seen before
ghci> :t return
return :: Monad m => a -> m a
That’s scary.
return
wraps an object in an IO
do
block is the return value of the function
What does this do?
helloWorld :: IO ()
helloWorld = do
return ()
putStrLn "Hello World!"
main
function
main :: IO ()
main = ...