Exploring Haskell: Types & Classes

exploring haskell types and classes

Code examples are adapted from Introduction to Functional Programming course.

Access to GHCi is available on repl.it to test out these snippets online.

Types

Evaluating an expression e.

e :: t -- This reads as e has type t, also used for type casting

Every valid expression has a type, which is calculated using type inference.

To get a type in GHCi use :t which is an abbreviation for :type command.

not False -- True

:t not False -- not False :: Bool

Basic Types

Some basic types that are common in other programming languages:

  • Bool - logical values
  • Char - single character
  • String - strings of characters
  • Int - fixed-precision integers
  • Integer - arbitrary-precision integers
  • Float - floating-point numbers
:t True -- Bool - logical values

:t 'H' -- Char - single character
:t "Hi" -- [Char] - strings of characters

:t 1 -- Num p => p
2^64 :: Int -- is out of the Int range (Overflow)

:t 2^65 -- Num p => p
2^65 :: Integer -- 36893488147419103232

:t 1.5 -- Fractional p => p

List Types

Lists in Haskell are polymorphic and can only contain a sequence of values with the same type.

:t [False, True, False] -- [False, True, False] :: [Bool]

:t ['a', 'b', 'c', 'd'] -- ['a', 'b', 'c', 'd'] :: [Char]

:t [['a'], ['b', 'c']] -- [['a'], ['b', 'c']] -- :: [[Char]]

Tuple Types

Tuples can contain sequence of values with different types

:t (False, True) -- (False, True) :: (Bool, Bool)

:t (False,'a',True) -- (False, 'a', True) :: (Bool, Char, Bool)

:t ('a', (False, 'b')) -- ('a', (False, 'b')) :: (Char, (Bool, Char))

:t (True, ['a', 'b']) -- (True, ['a', 'b']) -- :: (Bool, [Char])

Functions

A function is a mapping from values of one type to values of another type:

import Data.Char (isDigit) -- Necessary for isDigit to work
:t isDigit -- isDigit :: Char -> Bool

:t not -- not :: Bool -> Bool

-- Example functions
add (x, y) = x + y -- add :: Num a => (a, a) -> a

zeroto n = [0..n] -- zeroto :: (Num a, Enum a) => a -> [a]

Curried Functions

When a function returns as a result an another function it is called a curried function.

add' x y = x + y -- add' :: Num a => a -> a -> a

Both add and add' produce the same result, where add takes all arguments at the same time, and add' can consume one at a time.

-- Parenthesis in Haskell are right associative and are omitted for brevity.
mult x y z = x * y * z -- mult :: Num a => a -> (a -> (a -> a))

Why is Currying Useful?

Currying makes functions more flexible and allows partial application.

Creating a function that increments by one:

addOne = add' 1
addOne 2 -- 3

Conventions for Currying

To avoid excess parentheses when using curried functions there are two conventions:

  1. The -> in type definition associates to the right.

    Int -> Int -> Int -> Int -- Int -> (Int -> (Int -> Int))
    
  2. Function application is associated to the left.

    mult x y z -- ((mult x) y) z
    

Unless explicitly required, all functions in Haskell are defined in the curried form.

Polymorphic Functions

A function can be called polymorphic when its type contains one or more type variables

-- length takes a 'collection' of type 'a' and returns an 'Int'
:type length -- length :: Foldable t => t a -> Int

length [False, True] -- 2
length [1, 2, 3, 4] -- 4

-- More Examples

:t fst -- fst :: (a, b) -> a

:t head -- head :: [a] -> a

:t take -- take :: Int -> [a] -> [a]

:t zip -- zip :: [a] -> [b] -> [(a, b)]

:t id -- id :: a -> a

Overloaded Functions

A polymorphic function is called overloaded if its type contains one or more class constraints.

-- sum takes a list with numeric type 'a', and returns a value of type 'a'.
:t sum -- sum :: (Foldable t, Num a) => t a -> a

sum [1, 2, 3] -- 6
sum [1.1, 2.2, 3.3] - 6.6
sum ['a', 'b', 'c'] -- error

Classes

Haskell has a number of type classes:

  • Num - Numeric types
  • Eq - Equality types
  • Ord - Ordered types
:t (+) -- (+) :: Num a => a -> a -> a

:t (==) -- (==) :: Eq a => a -> a -> Bool

:t (<) -- (<) :: Ord a => a -> a -> Bool

And that's it for now.