Why programming still matters

Martin Sulzmann

Why programming still matters

What students usually think programming is:

What programming actually is:

Therefore, there is no need to worry. AI will not replace us. Copilot is just a tool.

Keep in mind:

High-level and low level programming languages

Overview

If ChatGPT can write, e.g., quicksort, in 5 seconds, why are we here?

Quicksort

Idea:

Let’s consider some examples where we write [x1,...,xn] to denote an array of n elements from x1 to xn.

[3,2,5,1,4]

Pick first element 3 as our pivot element.

lesser = [2,1]

greater = [5,4]


quicksort [2,1] => [1,2]

quicksort [5,4] => [4,5]


Then,

   quicksort [3,2,5,1,4]

= (quicksort [2,1])  + [3] + (quicksort [5,4])

= [1,2] + [3] + [4,5]

= [1,2,3,4,5]

Challenge: Implement Quicksort in 2min (without using google, …).

Quicksort in Haskell

quicksort [] = []
quicksort (p:xs) = (quicksort lesser) ++ [p] ++ (quicksort greater)
    where
        lesser = filter (< p) xs
        greater = filter (>= p) xs

5 lines of code. That’s it. In Haskell we write ++ for list concatenation.

The Haskell code directly corresponds to the quicksort specification.

Quicksort in C

The code below can also be found here

void display(int x[], int low, int high) {

  printf("\n x[] low = %d high =%d \n", low, high);

  for(; low <= high; low++) {
    printf("%d ", x[low]);
  }
}


void swap(int* x, int* y) {
  int temp = *x;
  *x = *y;
  *y = temp;
}



void quicksort(int x[],int left, int right){
   int i, j, pivot, temp;

   if(left < right){
      pivot=left;
      i=left;
      j=right;

      /*
       1. Partition array

           (a)
           From left and right compare against pivot element.
           Adjust i (upper left frontier) and j (lower right frontier).
           Swap if frontiers haven't met yet.

           (b)
           Swap so that pivot element is placed in the middle.

       2. Recursively quicksort

           (a)
           All elements lesser (or equal) than pivot element.
           (b)
           All elements greater than pivot element.

       */

      // (1a)
      while(i<j){
    while(x[i]<=x[pivot] && i<right) // (I1)
            i++;
    while(x[j]>x[pivot])            // (I2)
            j--;
         if(i<j){
       swap(&x[i], &x[j]);
         }
      }

      // (1b)
      swap(&x[pivot], &x[j]);

      // (2a)
      quicksort(x,left,j-1);
      // (2b)
      quicksort(x,j+1,right);

   }
}

/*

Further comments.

(I1) The side condition "i<right" ensures that we stay
     within valid array bounds.
     We might reach the case that i = right.
     Access to x[right] is valid, so we can safely evaluate
     x[i] <= x[pivot] and then abort the while loop because
     condition "i<right" no longer holds.

(I2)

*/

Some fun extension

Given n > 1000 integers, write a function to return the smallest 5 integers.

In class live coding.

Observations

Programming still matters because abstraction level determines how we can reason.

We can compare Haskell and C as follows.

C is a low-level language, great for reasoning at the machine level:

Haskell is a high-level language, great for reasoning at the math level:

Expressive types (to catch bugs at run-time)

Let’s play with lists in Haskell.

Some live coding.

Here’s the gist of it.

test1 = do let x = head (tail ([1]))
           print x

The above program type checks but running the program leads to a crash (“Prelude.head: empty list”).

Do you know similar situations in other languages?

How can we catch such bugs without having to run the program?

Idea: We make use of expressive types to represent program properties.

Dependent types in Haskell

In languages with parametric polymorphism we can mimic dependent types by encoding values via types. The general idea is to introduce phantom types. These are types where some of the type parameters are not connected to any program terms. We will see such an example shortly.

Here’s a representation of length-indexed lists. in Haskell.

-- Natural numbers.
data Zero = Zero
data Succ n = Succ n

-- Length-indexed lists.
data List a n where
    Nil :: List a Zero
    Cons :: a -> List a m -> List a (Succ m)

Some live demo based on the following Haskell playground code.

Can this be done in other languages? Yes.

Summary and outlook

Programming is about precision in a world of ambiguity.

This course is about:

where we focus on Haskell.

Some teaching materials were developed with the assistance of AI-based tools.