Last Updated: 2018-10-08 Mon 08:49

CSCI 2041 Lab05: Polymorphic Records

CODE DISTRIBUTION: lab05-code.zip

  • Download the code distribution every lab
  • See further setup instructions below

CHANGELOG: Empty

1 Rationale

Polymorphic functions have been illustrated previously such as functions that work on any kind of list. Data types can also be polymorphic/parametric. Unlike many typed programming languages, OCaml provides an extremely easy means to parameterize data based on a type. This is apparent from the use of array, list, and ref syntax which allows for any type of element to be used with these. OCaml's has uniform polymorphism for all its data constructions including Record types and Algebraic types which allow new types to work similarly to lists, arrays, and refs.

This lab covers two kinds of stacks which are both polymorphic. One is mutable while the other is mutable. Completing the lab will introduce one to issues associated with polymorphic record types. Semantic and style differences between mutable/immutable data are also present.

Associated Reading / Preparation

Grading Policy

  • Check-off 30%: Demonstrate to a TA that a student understands answers to questions. This must be done in person in groups of one or two. Check-offs can happen during the lab period of during a TA office hour.
  • Submit 70%: Submit required files according to the lab instruction. This can be done at any time and from anywhere with a network connection. Submitting does not require attending lab. All students must submit files even if they were checked off in a group during lab.

See the full policy in the syllabus.

2 Codepack

The codepack for the lab contains the following files:

File State Description
QUESTIONS.txt Edit Answer questions in the file to complete the lab
imu_stack.ml Provided Problems 1 & 2 file to analyze
mut_stack.ml Provided Problems 1 & 2 file to analyze
history.ml Provided Problem 3 file to analyze

3 Questions

Analyze the files in the provided codepack and answer the questions given in QUESTIONS.txt.

                           __________________

                            LAB 05 QUESTIONS
                           __________________


- Name: (FILL THIS in)
- NetID: (THE kauf0095 IN kauf0095@umn.edu)

Answer the questions below according to the lab specification. Write
your answers directly in this text file and submit it to complete the
lab.


PROBLEM 1: Mutable vs Immutable Stack Usage
===========================================

(A)
~~~

  Examine the code in `mut_stack.ml' which implements a mutable stack
  data structure using a new record type `mut_stack'.

  In a REPL, call the `make ()' function to create a `mut_stack' and
  demonstrate some `push / pop / top / poptop' operations with integers.

  What is the return value associated with each of the functions?


(B)
~~~

  In the type declaration for `mut_stack', explain the significance of
  the `'a' notation: what effect does it have on the kinds of stacks
  that can be created? Demonstrate the flexible nature of `mut_stack' in
  a REPL showing several kinds of stacks.


(C)
~~~

  Examine the code in `imu_stack.ml' which implements an immutable stack
  data structure using a new record type `imu_stack'.

  In a REPL, call the `make ()' function to create a `imu_stack' and
  demonstrate some `push / pop / top / poptop' operations with integers.

  What is the return value associated with each of the functions?

  What is very different about making repeated `push' calls on
  `imu_stack' compared to `mut_stack'?


PROBLEM 2: Weak vs Polymorphic Types
====================================

(A)
~~~

  An astute observer will see the following apparent change of type for
  `mut_stacks':
  ,----
  | # let int_stack = make ();;
  | # int_stack;;
  | - : '_weak1 mut_stack = {size = 0; data = []}
  | (*  ^^^^^^^   *)
  | (* what is '_weak1? *)
  | 
  | # push int_stack 5;;
  | - : unit = ()
  | 
  | # int_stack;;
  | - : int mut_stack = {size = 1; data = [5]}
  | (*  ^^^ *)
  | (* now its an int mut_stack ?? *)
  `----

  Read the first few paragraphs of the OCaml System Manual, Ch 5.1 to
  learn about weak types.
  [https://caml.inria.fr/pub/docs/manual-ocaml/polymorphism.html]

  Explain below the peculiar `'_weak1' type associated with an empty
  `mut_stack'. Is it the same as a polymorphic `'a' type?


(B)
~~~

  Consider the following sequence of operations starting with an `empty
  imu_stack'.

  ,----
  | # #use "imu_stack.ml";;
  | 
  | # let empty = make ();;
  | val empty : 'a imu_stack = {size = 0; data = []}
  | 
  | # let istack = push empty 5;;
  | val istack : int imu_stack = {size = 1; data = [5]}
  | 
  | # let sstack = push empty "hello";;
  | val sstack : string imu_stack = {size = 1; data = ["hello"]}
  | 
  | # empty;;
  | - : 'a imu_stack = {size = 0; data = []}
  `----

  Answer the following questions about the above.
  - What is the type of `empty' here?  Is it a weakly typed binding as
    discussed in the previous section?
  - Why is it possible to do both `push 5' and `push "hello"' into the
    `empty'?
  - Does pushing different types into `empty' change the type of
    `empty'?


(C)
~~~

  Consider the following sequence of operations which are nearly
  identical to the previous section except with the `mut_stack' type
  used.

  ,----
  | # #use "mut_stack.ml";;
  | 
  | # let empty = make ();;
  | val empty : '_weak2 mut_stack = {size = 0; data = []}
  | 
  | # push empty 5;;
  | - : unit = ()
  | 
  | # empty;;
  | - : int mut_stack = {size = 1; data = [5]}
  | 
  | # push empty "hello";;
  | Characters 11-18:
  |   push empty "hello";;
  |          ^^^^^^^
  | Error: This expression has type string but an expression was expected of type
  |      int
  | 
  `----

  Why does this sequence result in a type error?


PROBLEM 3: Tracking Stack History
=================================

(A)
~~~

  Examine the file `history.ml'. It performs a series of push operations
  on stacks and attempts to generate a history of the states the stack
  is in.  This is done first on the `imu_stack' and then on the
  `mut_stack'.

  In this file, do the operations `push' and `make' actually work on
  both `mut_stack' and `imu_stack' or is something else going on?
  Relate your answer to the `open' directives present in `history.ml'.


(B)
~~~

  Load `history.ml' into a REPL. Before doing so, you will need to
  ensure that the `Mut_stack' and `Imu_stack' modules are available by
  using the REPL's `#mod_use' directive as follows.
  ,----
  | # #mod_use "mut_stack.ml";;
  | ...
  | # #mod_use "imu_stack.ml";;
  | ...
  | # #use "history.ml";;
  | ...
  `----

  Show the output of running these three directives below.

  We discuss the modules/signatures later but note that `#mod_use'
  prints out information about the values and types present in a source
  file.


(C)
~~~

  Examine the two values established by `history.ml'
  - `imu_history' associated with the history of an `imu_stack'
  - `mut_history' associated with the history of a `mut_stack'

  Determine if the histories accurately reflect the different states
  that the stacks of undergone or not.  Describe anything strange/wrong
  that you observe particularly about `mut_history' and determine as
  best as you can WHY it is happening.

4 What to Understand

Ensure that you understand

  • The notion of a polymorphic data type: one that has an additional data type associated with it
  • The notion of weakly typed variables which usually only arise in the REPL
  • Mutable vs Immutable record fields
  • The utility of immutable data in tracking past states of data

5 Getting Credit: Submit and Check-off

  • Check-off your answers with a TA in person during lab or office hours.
  • Submit your completed QUESTIONS.txt file to Canvas under the appropriate lab heading. Make sure to paste in any new code and answers you were to write at appropriate locations in the file.

Author: Chris Kauffman (kauffman@umn.edu)
Date: 2018-10-08 Mon 08:49