Lab 7: OCaml 12:00 PM, Oct 22, 2017

Similar documents
Homework 6: Higher-Order Procedures Due: 10:00 PM, Oct 17, 2017

Homework 8: Matrices Due: 11:59 PM, Oct 30, 2018

Lab 10: OCaml sequences, comparators, stable sorting 12:00 PM, Nov 12, 2017

Homework 6: Higher-Order Procedures Due: 11:59 PM, Oct 16, 2018

The Design Recipe Fall 2017

(Provisional) Lecture 08: List recursion and recursive diagrams 10:00 AM, Sep 22, 2017

The Design Recipe Fall 2018

(Provisional) Lecture 22: Rackette Overview, Binary Tree Analysis 10:00 AM, Oct 27, 2017

Homework 3: Recursion Due: 11:59 PM, Sep 25, 2018

Homework 7: Subsets Due: 11:59 PM, Oct 23, 2018

(Provisional) Lecture 20: OCaml Fun!

Lab 1: Setup 12:00 PM, Sep 10, 2017

How to Design Programs

OCaml Style Guide Fall 2017

Racket Style Guide Fall 2017

Lecture 27: (PROVISIONAL) Insertion Sort, Selection Sort, and Merge Sort 10:00 AM, Nov 8, 2017

Intro. Scheme Basics. scm> 5 5. scm>

Homework 12: Tail Recursion and Analysis Due: 11:59 PM, Dec 4, 2018

Summer 2017 Discussion 10: July 25, Introduction. 2 Primitives and Define

Typed Racket: Racket with Static Types

Working with recursion. From definition to template. Readings: HtDP, sections 11, 12, 13 (Intermezzo 2).

Working with recursion

Lecture 3: Recursion; Structural Induction

The Typed Racket Guide

Introduction to Typed Racket. The plan: Racket Crash Course Typed Racket and PL Racket Differences with the text Some PL Racket Examples

CS115 - Module 10 - General Trees

A First Look at ML. Chapter Five Modern Programming Languages, 2nd ed. 1

CS115 - Module 9 - filter, map, and friends

CMSC 201 Fall 2016 Lab 09 Advanced Debugging

The name of our class will be Yo. Type that in where it says Class Name. Don t hit the OK button yet.

Data type built into Python. Dictionaries are sometimes found in other languages as associative memories or associative arrays.

Lab 10: Sockets 12:00 PM, Apr 4, 2018

Lecture 5: Implementing Lists, Version 1

CS131 Typed Lambda Calculus Worksheet Due Thursday, April 19th

Functional abstraction. What is abstraction? Eating apples. Readings: HtDP, sections Language level: Intermediate Student With Lambda

Functional abstraction

CMSC 330: Organization of Programming Languages. Functional Programming with Lists

CMSC 330: Organization of Programming Languages. Functional Programming with Lists

Programming. We will be introducing various new elements of Python and using them to solve increasingly interesting and complex problems.

Python lab session 1

Functions that return lists

Welcome Back. CSCI 262 Data Structures. Hello, Let s Review. Hello, Let s Review. How to Review 1/9/ Review. Here s a simple C++ program:

Welcome Back. CSCI 262 Data Structures. Hello, Let s Review. Hello, Let s Review. How to Review 8/19/ Review. Here s a simple C++ program:

Tail Calls. CMSC 330: Organization of Programming Languages. Tail Recursion. Tail Recursion (cont d) Names and Binding. Tail Recursion (cont d)

SCHEME 7. 1 Introduction. 2 Primitives COMPUTER SCIENCE 61A. October 29, 2015

CS 321 Programming Languages

SNU Programming Language Theory

Module 3: New types of data

Lists. Prof. Clarkson Fall Today s music: "Blank Space" by Taylor Swift

Lab 5: Java IO 12:00 PM, Feb 21, 2018

Input, output, and sequence

(Provisional) Lecture 32: Estimated Value, Minimax, Functional Data 10:00 AM, Nov 20, 2017

CS50 Supersection (for those less comfortable)

CMSC 330: Organization of Programming Languages. Operational Semantics

Lecture 8: Iterators and More Mutation

For this chapter, switch languages in DrRacket to Advanced Student Language.

Deferred operations. Continuations Structure and Interpretation of Computer Programs. Tail recursion in action.

CSc 520 Principles of Programming Languages

VISUAL GUIDE to. RX Scripting. for Roulette Xtreme - System Designer 2.0. L J Howell UX Software Ver. 1.0

printf( Please enter another number: ); scanf( %d, &num2);

Repetition Through Recursion

If Statements, For Loops, Functions

CS115 INTRODUCTION TO COMPUTER SCIENCE 1. Additional Notes Module 5

Scheme: Expressions & Procedures

Intro to Programming. Unit 7. What is Programming? What is Programming? Intro to Programming

Module 8: Local and functional abstraction

Spring CS Homework 3 p. 1. CS Homework 3

CS 314 Principles of Programming Languages. Lecture 16

CSE 130, Winter 2011: Final Examination

CS558 Programming Languages

MP 3 A Lexer for MiniJava

CSCI0170. Today s topics. Predicates Natural Number recursion Recursion Diagrams List recursion A first glance at the design recipe

Principles of Programming Languages Topic: Functional Programming Professor L. Thorne McCarty Spring 2003

Hands-On Lab. Introduction to F# Lab version: Last updated: 12/10/2010. Page 1

Case Study: Undefined Variables

15-122: Principles of Imperative Computation, Fall 2015

CS Lecture 6: Map and Fold. Prof. Clarkson Fall Today s music: Selections from the soundtrack to 2001: A Space Odyssey

Using the Zoo Workstations

Lecture Programming in C++ PART 1. By Assistant Professor Dr. Ali Kattan

Language Proposal: tail

CS 360: Programming Languages Lecture 10: Introduction to Haskell

An Explicit Continuation Evaluator for Scheme

Decisions, Decisions. Testing, testing C H A P T E R 7

SCHEME 10 COMPUTER SCIENCE 61A. July 26, Warm Up: Conditional Expressions. 1. What does Scheme print? scm> (if (or #t (/ 1 0)) 1 (/ 1 0))

Finding and Fixing Bugs

COSE212: Programming Languages. Lecture 3 Functional Programming in OCaml

Programming Languages and Techniques (CIS120)

Programming Languages and Techniques (CIS120)

TOPIC 2 INTRODUCTION TO JAVA AND DR JAVA

CMSC 330: Organization of Programming Languages. OCaml Imperative Programming

Animations involving numbers

Lisp. Versions of LISP

Typed Scheme: Scheme with Static Types

5. Control Statements

CSCI 2041: Pattern Matching Basics

Module 5: Lists. Readings: HtDP, Sections 9, 10.

Lecture: Functional Programming

List Functions, and Higher-Order Functions

Lesson 10A OOP Fundamentals. By John B. Owen All rights reserved 2011, revised 2014

The design recipe. Readings: HtDP, sections 1-5. (ordering of topics is different in lectures, different examples will be used)

Transcription:

CS17 Integrated Introduction to Computer Science Hughes Lab 7: OCaml 12:00 PM, Oct 22, 2017 Contents 1 Getting Started in OCaml 1 2 Pervasives Library 2 3 OCaml Basics 3 3.1 OCaml Types........................................ 3 3.2 OCaml Syntax....................................... 4 3.3 OCaml Loves Types and So Should You......................... 4 4 Options (Not Optional) 4 5 The Design Recipe, in OCaml! 5 5.1 Design Recipe for Atomic Data.............................. 6 6 List Recursion 7 Objectives By the end of this lab, you will know: ˆ OCaml types ˆ OCaml syntax ˆ how and when to use options By the end of this lab, you will be able to: ˆ use Atom and compile OCaml code on the command line ˆ write recursive procedures based on built-in recursive types like lists ˆ write recursive procedures based on user-defined variant types ˆ pattern match in Ocaml

1 Getting Started in OCaml So far in CS 17, we ve written and run all our code in an Integrated Development Environment, or IDE. This means that we could run our code within the window that we were writing it in. But sadly, as we move on to OCaml, we have to say good bye to our friend DrRacket. Instead, we will be writing our code in the text editor Atom, and then running it from the command line! To get started, open up the terminal, and type atom & at the prompt. Wait a few seconds for Atom to load, and then mouse over the Atom window to activate it. Note: Before we move on, please configure your Atom to allow for OCaml syntax highlighting. Look at the OCaml installation guide on the website for help. Now you can either open an existing OCaml file or create a new one. Since you don t yet have any existing OCaml files, let s go ahead and create one. Type in the following lines of code: let a = 17 ;; let b = a ;; a + b ;; To save your program to a file, type Ctrl s. Give it an informative name, such as test.ml. (All OCaml files should end with the extension.ml.) You ll notice at this point that the colors of your text changed! This happened because Atom has intelligent syntax highlighting, meaning the editor will informatively color different parts of your program to make it easier for you to code and debug. Now, let s return to your terminal window and run your program. Note that in order to run your program from the command line, you need to first navigate into the directory in which your file is saved. 1. To check if your code has any syntax errors, you can run ocaml test.ml. If your code is error-free, this will output nothing! Otherwise, it provides a useful way to hunt down syntax errors in your code before moving on. 2. You can then run your code like this: ocaml < test.ml. Use this option when you want to see what your program outputs (e.g. the results of your test cases). 3. Alternatively, you can run the OCaml REPL, or Read-Evaluate-Print-Loop, yourself, by entering ocaml on the command line. Then, type #use "test.ml" ;; - this will read your program and evaluate each top level expression. You can also type OCaml procedures directly into the REPL to see what they will output. Don t forget the quotation marks (or the two semi-colons)! To exit from the OCaml interpreter, type either Ctrl-d or exit 1 ;;. Going back to your test.ml file, let s try entering a bad program. We might, for example, refer to a procedure that doesn t yet exist: factorial 5 ;; 2

After typing this in, let s check for syntax errors by entering ocaml test.ml into the terminal. You should now see an error message showing what caused the problem. You should also see a line indicating which line contains the error. Let s try something else, like making a spelling mistake: let five = 5 ;; fvie + 6 ;; Again, you will see a similar error message, but at the end, it will also ask you Did you mean five Whenever you finish writing a program, make sure to save it, and then exit Atom by closing your Atom window (Ctrl q). 2 Pervasives Library OCaml has lots of procedures and types predefined for you to use. Most of them are contained in libraries. To make use of procedures defined in libraries, you need to use a directive, a command that tells OCaml to import the library. There is one exception, however: the Pervasives library is preloaded when you start OCaml, so the definitions in that library are immediately accessible. The Pervasives Library, in essence, contains the procedures that you can use without defining them yourselves ( OCaml Builtins, so to speak). You can find out which procedures are defined for you here: http://caml.inria.fr/pub/docs/manual-ocaml/libref/pervasives.html Note: When you start up OCaml, you will see what looks like an error message, and says The files /course/cs017/src/ocaml/cs17setup.cmo and /local/bin/ocaml disagree over interface Pervasives. This is because we have modified some procedures (like + and * ) so that their behavior is safer for people new to programming. You can safely ignore this message. 3 OCaml Basics Before we begin, make sure to include our OCaml setup at the top of all of your assignments to make sure you have access to all of our functions. To get the CS17 OCaml version of a teachpack, first run the following command from the directory in which you are working: cp /course/cs0170/src/ocaml/cs17setup.ml. This will copy the teachpack to your current directory. Then include the following line at the top of your file #use "CS17setup.ml" ;; Note that you will need to do this at the top of all of your OCaml assignments! 3

3.1 OCaml Types Task: For each OCaml expression below, state the type of its value (not its value). For example, 3 has the value 3, but the type int. Some other OCaml types include float and string. If there is a type clash, meaning the expression s type is not well-defined, explain why. Please use the OCaml interpreter only to check your answers. 1. 3 2. 3.0 3. 3 + 3.0 4. 3 / 2 5. fun x ->x / 2.0 6. [1; 2; [3; 4]] 7. (17, ["shiba"; "labrador"; "pug"; "corgi"], (false, true)) 8. [(1, 2, []); (3, 4, [5; 6; 7])] 9. if test then 1 else false 10. let rec count_pupper alod = match alod with [] - > 0 "pupper" :: tail - > 1 + count_pupper tail _ :: tail - > count_pupper tail 3.2 OCaml Syntax Task: Below, we have given you some expressions in Racket. Convert them to OCaml, and then execute them by running ocaml to ensure that your code is correct. When writing fibonacci, you may find it useful to use the OCaml when keyword, which checks a condition in a match case. An example of when usage can be found in the code for factorial in the next section of the lab. (+ 17 18) (* (+ 19 21) ( - 4 3)) (define (list - length alod) (cond [(empty? alod) 0] [(cons? alod) (+ 1 (list - length (rest alod)))])) (define (fibonacci x) (cond [(<= x 1) 1] [(> x 1) (+ (fibonacci ( - x 1)) (fibonacci ( - x 2)))])) 4

3.3 OCaml Loves Types and So Should You Unlike Racket, OCaml is a statically typed language. This means that OCaml will produce an error or refuse to read and print if the argument passed does not match the expected type. Clarifying your types helps the user of your function to know what types of arguments to put in and what order they go. This is analogous to the type signatures you wrote in Racket. For example: let rec factorial (x: int) : int = match x with x when x <= 1 - > 1 _ - > x * factorial (x - 1) ;; requires that you give factorial an int. If you give it a float, or any other type for that matter, it will throw an error. Note: We require you to type annotate all of your aguments and return types. 4 Options (Not Optional) Options are an important example of a parameterized variant type that is built in to OCaml: type 'a option = None Some of 'a In words, an 'a option is either a None or a Some applied to an argument of type 'a. Options are useful when writing a procedure that might not produce a value, such as a procedure that looks up a word in a dictionary, since that word might not be in the dictionary! Formally, a dictionary is a set of key-value pairs. For instance, in an English language dictionary, the keys are words and the values are the corresponding definitions. If you look up a word that is in the dictionary, then what you find is the corresponding definition. But if you look up a word that is not in the dictionary, then you don t find anything at all. What should a procedure that looks up keys in a dictionary produce when the key is not found? One possibility is the string "key not found". But what if there is a word in the dictionary whose definition is precisely "key not found"? If such a definition is possible, how could you distinguish between a successful and an unsuccessful lookup? A better alternative for when lookup fails is to produce a special value that cannot possibly be confused with a definition this is exactly what options allow you to do. Here is a data definition for dictionaries: type ('a, 'b) dict = ('a * 'b) list ;; (* Examples of dict *) [(1, 1); (2, 4); (3, 9); (4, 16)] ;; [(1, "one"); (2, "two"); (3, "three")] ;; 5

Task: Write a procedure, lookup, which consumes a dictionary and a key, and produces an option on the corresponding value. Examples: lookup [(1, 1); (2, 4); (3, 9); (4, 16)] 3 => Some 9 lookup [(1, "one"); (2, "two"); (3, "three")] 2 => Some "two" lookup [(1, "one"); (2, "two"); (3, "three")] 4 => None You ve reached a checkpoint! Please call over a lab TA to review your work. 5 The Design Recipe, in OCaml! In this part of the lab, we will review the design recipe for atomic data and the design recipe for mixed data, applying the exact same recipe as before while programming (the exact same procedures as before). 5.1 Design Recipe for Atomic Data The design recipe carries over more or less exactly from one programming language to another. The only difference between applying it to OCaml, as compared to Racket, is that the type signature does not appear in a comment. Instead, it appears as actual code. In particular, the call structure of every procedure you write in OCaml should be annotated with the types it consumes and the type it produces. For example, here is the call structure together with the type signature for the flip procedure in OCaml: let flip (alop : string*string list) : string*string list =... As for testing, your old friends check_expect, and a new tool, check_within are available for all your testing needs! You can use check_within to check the value of floats. To use check_within, pass in the procedure and its arguments, the expect result, and the tolerance, i.e. the decimal value to which we want to test the accuracy. In OCaml, they have underscores instead of hyphens, and are used like this: check_expect actual expected check_within actual expected within For example, here s the flip procedure in OCaml, developed by following the design recipe. Notice how much shorter it is than its Racket counterpart, because we can use tuples! 6

#use "CS17setup.ml" ;; (* Inputs: a list of pairs of strings, alop *) (* Output: a list where the ith element is in the same position, but the order of its elements is reversed *) let rec flip (alop : (string*string) list) : (string*string) list = match alop with [] - > [] (a, b) :: tail - > (b, a) :: (flip tail) ;; "Test cases for flip" ;; check_expect (flip []) [] ;; check_expect (flip [("hello", "world")]) [("world", "hello")] ;; check_expect (flip [("i", "love"); ("ocaml", "programming")]) [("love", "i"); ("programming", "ocaml")] ;; Task: Follow the design recipe to implement a procedure that converts degrees in Fahrenheit to degrees in Celsius. Hint: C = 5 9 (F 32), where C denotes degrees in Celsius, and F, degrees in Fahrenheit. You ve reached a checkpoint! Please call over a lab TA to review your work. 6 List Recursion In programming, as in natural languages, when one learns a new language, the tendency at first is to try to write programs in an old language, and then translate those programs into the new one. Sometimes this fails outright; more often it is possible, but bad style. We d like you to avoid the temptation to write Racket programs in OCaml. So in this problem we are explicitly forbidding the use of List.hd and List.tl, OCaml s equivalent of first and rest. You must use pattern matching instead. Here is the template for writing procedures that recur on lists in OCaml: let rec proc (alod : 'a list): <return - type> = match alod with [] - > head :: tail - >... head... (proc tail)... And here is the familiar length procedure: let rec length (alod : 'a list) : int = match alod with [] - > 0 _ :: tail - > 1 + length tail Task: Write the familiar procedure sum_list in OCaml. This procedure consumes a list of ints and produces the sum of the ints in that list. 7

Task: Rewrite sum_list using List.fold_right (or List.fold_left). 1 Hint: Here s how to get started: let sum_list alon = List.fold_right... Since sum_list applies to a list of integers, its type is int list ->int. Likewise, it is possible to apply List.fold_right to a few, but not all, of its arguments until its type is also int list ->int. Task: Define a type, base, that has one of four values "A", "C", "G", "T". Task: Write a procedure, complement, that takes in a base and returns its complement. Note: "A" and "T" are complements of each other, and "C" and "G" are complements of each other. Task: Write the procedure memberp : 'a * 'a list ->bool, which consumes a tuple consisting of a datum and a list of data, and determines whether that datum is in that list. For example: memberp (3, [1; 2; 3; 4; 5]) => true Note: In OCaml, you cannot use? to distinguish predicates, because the? character is reserved for another use. As a refresher, a predicate is a one-argument procedure that returns a boolean, such as even? or empty? in Racket. An alternative is to append a P to the end of the predicate s name: e.g., memberp. The P stands for predicate. You are at the grocery store, shopping for fruit. You want apples, bananas, and oranges, each of which is only purchaseable in a group (you cannot buy individual fruits). You get to the checkout, and want to know how many items are in your basket. Task: Define a type, fruit, that has an int parameter. There will be three types, apple, orange, and banana. Task: Write a procedure, num-fruits, that takes in a list of fruits and outputs the total number of fruits in the list. For example, a list of apple(3), banana(4) should output the integer 7. Task: Challenge (Time Permitting): Implement fold in OCaml. Once a lab TA signs off on your work, you ve finished the lab! Congratulations! Before you leave, make sure both partners have access to the code you ve just written. Please let us know if you find any mistakes, inconsistencies, or confusing language in this or any other CS17document by filling out the anonymous feedback form: http://cs.brown.edu/ courses/cs017/feedback. 1 You will learn the difference between these two procedures soon enough! 8