Expressions, Functions and the Substitution Model

In Haskell, computation is done on expressions. Here are some examples:

3 + 4

sqrt 9.0

sqrt (3 + 6)

Note that expressions have a value and that value has some type. 

3 + 4  => 7  : Int

sqrt 9.0  => 3.0  : Float

sqrt (3 + 6)  => 3.0  : Float

We can define functions which take an input value of some type and output the value of an expression using the input.  Whenever we define a function we usually declare the type of that function.

square :: Float -> Float
square x = x * x

hypotenuse :: Float -> Float -> Float
hypotenuse a b = sqrt (square a + square b)

Observe that the function square takes an input which is a Float and returns a value which is a Float.  Note that the function hypotenuse takes two Floats and returns a Float.  We will discuss later why the type for that function is written so strangely. 

Suppose we wish to compute the value of the following expression:

hypotenuse (3 + 2) (3 * 4)

To evaluate that expression we would simply substitute the expression definition of the function hypotenuse and replace its parameters with the values of its argument expressions:

hypotenuse (3 + 2) (3 * 4) =>                            -- substitute into the body of hypotenuse
sqrt (square (3+2)  + square (3 * 4))  =>        -- evaluate the arguments of square
sqrt (square 5  + square 12)  =>                        -- substitute into the body of square
sqrt (5 * 5 + 12 * 12)    =>                                  -- evaluate the argument of sqrt
sqrt (169) =>
13.0

We will find this substitution model quite useful as expressions get more complex.
 

Application :  Manipulating Words and Sentences

We will consider an application of manipulating words and sentences.  The values of both words and sentences will be of the type Language.  We will have two constructor functions word and sent which take a String and convert it to a Language object.

The following is a list of operators that we can perform on Language objects.

firstItem :: Language -> Language                 -- gives the first letter or word of a word or sentence
lastItem :: Language -> Language                 -- gives the last letter or word of a word or sentence
butFirst :: Language -> Language                 -- gives everything BUT the first letter or word of a word or sentence
butLast :: Language -> Language                 -- gives everything BUT the last letter or word of a word or sentence
item :: Int -> Language -> Language             -- gives the nth letter or word of a word or sentence
count :: Language -> Int                                  -- gives the number of letters or words of a word or sentence
(
+++)  :: Language -> Language->Language   -- concatenate two Language objects together
empty :: Language -> Bool                             -- determines if a word or sentence is empty
member :: Language -> Language->Bool     -- determines if a letter or word is contained in a word or sentence
wordToSent :: Language -> Language        -- converts a word to sentence of one word
sentToWord:: Language -> Language         -- converts a sentence to a single word

Consider the following example expressions:

word "computer" +++ word "s"    => computers : Language

sent "foundations of computer" +++ word "science"  => [foundations of computer science] : Language

count(butFirst (word "dogs"))  => 3 : Int

Consider the following function definitions.  Can you figure out what they do?

addS :: Language -> Language
addS w = w +++ word "s"

thirdPerson :: Language -> Language
thirdPerson verb = sent "she" +++ addS verb
 

Application : Quilts

Now we will look at building expressions which are not composed of number or language objects but are instead made up of quilt images.  The basic building blocks of our quilts will be predefined basic blocks of type Image.

    testBB

    cornerBB

       novaBB

    rcrossBB

We can manipulate blocks with two predefined operators:

quarterTurnRight :: Image -> Image         -- rotates a quilt by a quarter turn right

stack :: Image -> Image -> Image               -- stacks two quilts (of equal width)

We can display a quilt by using the function draw.  Consider the following expressions and figure out what they will display.

draw (stack (quarterTurnRight testBB) rcrossBB)

draw (quarterTurnRight (stack testBB testBB))