Lecture 04 Types

Joseph Haugh

University of New Mexico

What is a Type?

  • A type is the name we give to a set of values
  • For example the Bool type in Haskell has the True and False values

Type Signatures

  • In Haskell the type of a function is written separately
  • We use the notation v :: T, where v is a value and T is a type when writing a type signature
  • This means that the value v has type T

Function Types

  • A function is denoted by a −>;

  • A function T −> U means a function takes as an argument a value of type T and returns a value of type V

  • Function Examples

    add1 :: Int -> Int 
    add1 x = x + 1
    
    notNot :: Bool -> Bool 
    notNot b = not (not b)

Type Errors

  • A type error occurs when a function receives a type it doesn’t expect

  • For example:

    2 * True
  • This throws an error because (*) expects two numbers not a number and a Bool

Type Inference

  • You can leave off types in Haskell but somehow everything still has a type when queried
  • This is because Haskell has type inference
  • Type inference means that the compiler will try to infer the type of every value at compile time. If it fails then you get a type error

Inspecting Types

  • In ghci you can inspect the type of a value using or

    ghci> not True 
    False 
    ghci> :t not True 
    Bool

Basic Types

  • Bool - True or False
  • Char - Single character
  • String - List of characters
  • Int - 64 bit int
  • Float/Double - single/double precision floating point

Lists

  • List is among the most important types in Haskell
  • A list holds a sequence of values
  • We denote a list type with square brackets ([])
  • For example [[Int]] means list of Ints
  • Another example [[Bool]] means list of list of Bools
  • The type of a list has nothing to do with its length

List Examples

ghci> :t [1,2,3] 
[Int] 
ghci> :t [True, False] 
[Bool] 
ghci> :t [1,True] 
Error: Cannot have list with Int and Bool

Tuples

  • Tuples hold a limited number of values together
  • We denote a tuple type with parentheses (())
  • For example (Int, Float) means a tuple of an Int and a Float
  • Another example (Int, Float, Bool) means a tuple of an Int, Float and a Bool
  • The type of a tuple tells you how many elements it has

Tuple Examples

ghci> :t (1,False) 
(Int, Bool) 
ghci> :t (False,1) 
(Bool, Int) 
ghci> :t ((1,False),1.0) 
((Int, Bool),Float)

Lambdas

  • Lambdas introduce a localized function
  • Haskell makes heavy use of lambdas
  • Lambdas are denoted by [args] −> [body]

Lambda Examples

ghci> f = \x -> x + 1 
ghci> f 1 
2 
ghci> g = \b -> not b 
ghci> g True
False

Curried Functions

  • Every function can be transformed into a function of 1 argument
  • This is possible by being able to return functions from functions
  • This transformation is called currying
  • All functions in Haskell are curried

Curry Examples

Non curried function:

prod :: (Int, Int) -> Int 
prod (x, y) = x * y

Curried version:

prod :: Int -> Int -> Int 
prod x y = x * y

Can be thought of as:

prod :: Int -> (Int -> Int) 
prod x y = x * y

Or more explicitly:

prod :: Int -> (Int -> Int) 
prod = \x -> (\y -> x * y)

Curry Examples

Curry Examples Non curried three arg function:

add3 :: (Int, Int,Int) -> Int 
add3 (x, y, z) = x + y + z

Curried version:

add3 :: Int -> Int -> Int -> Int 
add3 x y z = x + y + z

Explicit Version:

add3 :: Int -> (Int -> (Int -> Int)) 
add3 = \x -> (\y -> (\z -> x + y + z))

Why Curry?

  • It is often useful to be able to partially apply a few arguments of a function
  • Many functions we will see later accept functions of 1 argument
  • You can take your many argument and partially apply it to be able to pass it to these functions

Exercise

Write out the curried and explicit versions of the following function:

foo :: (Int, String, Float) -> Int
foo (x, s, f) = x

Exercise

Write out the curried and explicit versions of the following function:

foo :: (Int, String, Float) -> Int
foo (x, s, f) = x

foo :: Int -> String -> Float -> Int
foo x s f = x

foo :: Int -> (String -> (Float -> Int))
foo = \x -> (\s -> (\f -> x))