All the operations used in the expression are over integers. a takes a pair as argument. (a pair is also a tuple, or more specifically, a 2-tuple)

Similar documents
Polymorphism and Type Inference

cs242 Kathleen Fisher Reading: Concepts in Programming Languages, Chapter 6 Thanks to John Mitchell for some of these slides.

Polymorphism and Type Inference

Type Systems, Type Inference, and Polymorphism

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

Begin at the beginning

Handout 2 August 25, 2008

Datatype declarations

A Second Look At ML. Chapter Seven Modern Programming Languages, 2nd ed. 1

Lists. Michael P. Fourman. February 2, 2010

Types and Type Inference

If we have a call. Now consider fastmap, a version of map that uses futures: Now look at the call. That is, instead of

CS109A ML Notes for the Week of 1/16/96. Using ML. ML can be used as an interactive language. We. shall use a version running under UNIX, called

Processadors de Llenguatge II. Functional Paradigm. Pratt A.7 Robert Harper s SML tutorial (Sec II)

Standard ML. Curried Functions. ML Curried Functions.1

CSE 341 Section 5. Winter 2018

OCaml. ML Flow. Complex types: Lists. Complex types: Lists. The PL for the discerning hacker. All elements must have same type.

Software System Design and Implementation

Lists. Adrian Groza. Department of Computer Science Technical University of Cluj-Napoca

CS558 Programming Languages

CS558 Programming Languages

Currying fun f x y = expression;

INF 212/CS 253 Type Systems. Instructors: Harry Xu Crista Lopes

The type checker will complain that the two branches have different types, one is string and the other is int

Chapter 3 Linear Structures: Lists

F28PL1 Programming Languages. Lecture 14: Standard ML 4

CS 11 Haskell track: lecture 1

CSC324- TUTORIAL 5. Shems Saleh* *Some slides inspired by/based on Afsaneh Fazly s slides

Chapter 3 Linear Structures: Lists

Tail Recursion: Factorial. Begin at the beginning. How does it execute? Tail recursion. Tail recursive factorial. Tail recursive factorial

Fall 2017 Discussion 7: October 25, 2017 Solutions. 1 Introduction. 2 Primitives

Sample Exam; Solutions

INF 212 ANALYSIS OF PROG. LANGS Type Systems. Instructors: Crista Lopes Copyright Instructors.

Static Checking and Type Systems

Type Checking and Type Inference

Functors signature Order = sig functor name type elem (structname:signature) = structure definition; val le : elem*elem -> bool end; elem

A Third Look At ML. Chapter Nine Modern Programming Languages, 2nd ed. 1

CSc 372. Comparative Programming Languages. 4 : Haskell Basics. Department of Computer Science University of Arizona

Functional Programming

Note that pcall can be implemented using futures. That is, instead of. we can use

Types, Type Inference and Unification

SML A F unctional Functional Language Language Lecture 19

Mini-ML. CS 502 Lecture 2 8/28/08

PROGRAMMING IN HASKELL. CS Chapter 6 - Recursive Functions

CSE 307: Principles of Programming Languages

Programming in Standard ML: Continued

CSE 307: Principles of Programming Languages

COSE212: Programming Languages. Lecture 3 Functional Programming in OCaml

Short Notes of CS201

Types and Type Inference

CIS24 Project #3. Student Name: Chun Chung Cheung Course Section: SA Date: 4/28/2003 Professor: Kopec. Subject: Functional Programming Language (ML)

Side note: Tail Recursion. Begin at the beginning. Side note: Tail Recursion. Base Types. Base Type: int. Base Type: int

CS201 - Introduction to Programming Glossary By

Homework 5. Notes. Turn-In Instructions. Reading. Problems. Handout 19 CSCI 334: Spring (Required) Read Mitchell, Chapters 6 and 7.

SCHEME 8. 1 Introduction. 2 Primitives COMPUTER SCIENCE 61A. March 23, 2017

Announcements. CSCI 334: Principles of Programming Languages. Lecture 5: Fundamentals III & ML

CSCI-GA Scripting Languages

Exercises on ML. Programming Languages. Chanseok Oh

A quick introduction to SML

From Templates to Folds

Fall 2018 Discussion 8: October 24, 2018 Solutions. 1 Introduction. 2 Primitives

Functional Programming

Data Types The ML Type System

Spring 2018 Discussion 7: March 21, Introduction. 2 Primitives

Practice problems Set 2

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

Type Inference Systems. Type Judgments. Deriving a Type Judgment. Deriving a Judgment. Hypothetical Type Judgments CS412/CS413

02157 Functional Programming. Michael R. Ha. Lecture 2: Functions, Types and Lists. Michael R. Hansen

Functional Paradigm II

Plan (next 4 weeks) 1. Fast forward. 2. Rewind. 3. Slow motion. Rapid introduction to what s in OCaml. Go over the pieces individually

Dialects of ML. CMSC 330: Organization of Programming Languages. Dialects of ML (cont.) Features of ML. Functional Languages. Features of ML (cont.

Specification and Verification in Higher Order Logic

CS 312. Lecture April Lazy Evaluation, Thunks, and Streams. Evaluation

CSc 372 Comparative Programming Languages. 4 : Haskell Basics

Assignment 0. Computer Science 52. Due Friday, September 7, 2018, at 5:00 pm

CS131 Typed Lambda Calculus Worksheet Due Thursday, April 19th

CPS Conversion. Di Zhao.

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

CSC312 Principles of Programming Languages : Functional Programming Language. Copyright 2006 The McGraw-Hill Companies, Inc.

Online Resource. Online introductory book on programming in SML (Standard ML): online.pdf

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

PROGRAMMING IN HASKELL. Chapter 2 - First Steps

Lecture 2: The Basis of SML

COS 126 General Computer Science Spring Written Exam 1

CSCC24 Functional Programming Typing, Scope, Exceptions ML

Introduction to Programming Using Java (98-388)

Higher-Order Functions

Control Structures. Lecture 4 COP 3014 Fall September 18, 2017

Values (a.k.a. data) representation. Advanced Compiler Construction Michel Schinz

Values (a.k.a. data) representation. The problem. Values representation. The problem. Advanced Compiler Construction Michel Schinz

News. Programming Languages. Complex types: Lists. Recap: ML s Holy Trinity. CSE 130: Spring 2012

Case Study: Undefined Variables

ML Built-in Functions

Chapter 1. Fundamentals of Higher Order Programming

The Algol family and ML

CS152: Programming Languages. Lecture 11 STLC Extensions and Related Topics. Dan Grossman Spring 2011

Overloading, Type Classes, and Algebraic Datatypes

A Brief Introduction to Standard ML

Defining Functions. CSc 372. Comparative Programming Languages. 5 : Haskell Function Definitions. Department of Computer Science University of Arizona

Patterns The Essence of Functional Programming

Transcription:

Weekly exercises in INF3110 week 41 6-10.10.2008 Exercise 1 Exercise 6.1 in Mitchell's book a) fun a(x,y) = x+2*y; val a = fn : int * int -> int All the operations used in the expression are over integers. a takes a pair as argument. (a pair is also a tuple, or more specifically, a 2-tuple) b) fun b(x,y)=x+y/2.0; val b = fn : real * real -> real From 2.0 we know that all the operations must be performed over reals. b takes a pair as argument. c) fun c(f)=fn y=>f(y); y is an argument of some type 'a. Since f is applied to y, it must have function type 'a -> 'b. c takes f as an argument, which is applied to y, hence the type of c. Example of usage: c(fn (a,b,c)=>5+a+b+c); [it = fn : int * int * int -> int ] c(op +); [it = fn : int * int -> int] c(op +)(2,3); [it = 5] val c = fn : ('a -> 'b) -> 'a -> 'b

d) fun d(f,x)=f(f(x)); val d = fn : ('a -> 'a) * 'a -> 'a The type of x is some type 'a. f must have a function type from 'a to 'a (since f is applied to itself which is applied to x). d takes a pair consisting of the function f (with type 'a->'a) and x:'a. Example of usage: d(fn(a)=>a+1,5); [it = 7] e) fun e(x,y,b)=if b(y) then x else y; val e = fn : 'a * 'a * ('a -> bool) -> 'a e takes three arguments. By the definition x and y must have the same type (restriction on the if-then-else construct in ML), namely 'a. b must take something of type 'a and return a boolean, since it is used as a condition. Example of usage: e(2,3,fn(a)=>a=2); [it = 3] e(2,3,fn(a)=>a=3); [it = 2] Exercise 2 a) Exercise 6.4 in Mitchell's book fun Y f x = f (Y f) x; val Y = fn : (('a -> 'b) -> 'a -> 'b) -> 'a -> 'b fun F f x = if x=0 then 1 else x*f(x-1); val F = fn : (int -> int) -> int -> int val factorial = Y F; val factorial = fn : int -> int Y is a function which takes a function as a first argument, which applied to an argument of type 'a gives something of type 'b. Since Y is a fixed-point operator, Y must be applied to a "functional", like the function F in a.

Example of usage: factorial(5); [it = 120] Sidenote: In Scheme, Y, F and factorial is written like this: (define ((Y f) x) ((f (Y f)) x)) (define ((F f) x) (if (= x 0) 1 ( * x (f (1- x))))) (define factorial (Y F)) b) Apply F to the identity function (fn x => x) and the following arguments: 0, 1, 2, 3. What is supposed to be the result? Why? Is F the factorial function? Explain. - F (fn x => x) 0; val it = 1 : int - F (fn x => x) 1; val it = 0 : int - F (fn x => x) 2; val it = 2 : int - F (fn x => x) 3; val it = 6 : int But: - F (fn x => x) 4; val it = 12 : int (0->1, 1->0, 2->2, 3->6, 4->12) "F (fn x => x) 0" gives 1 since the first branch of the conditional is applied. "F (fn x => x) 1" gives 0 since 1*f(0) = 1*0 = 0 (f is the identity function). F is not a recursive function: gives "F (fn x => x) n". n*(n-1)

Exercise 3 Exercise 6.5 in Mitchell's book fun f(g,h) = g(h) + 2; 1. The following shows the assignment of type to nodes: (lambda) : r / \ / \ / @ : v / / \ / / \ / @ : u 2 : int + : A @ : t g : tg h : th where A =def= int->int->-int. 2. Constraints (1) tg = th -> t (2) int -> (int -> int) = t -> u (3) u = int -> v (4) r = (tg * th) -> v 3. Substitution From (2) we get t = int and u = int -> int. Using this in (3) we get: v = int, and thereby, from t=int,(1) and (4) we get r = (th->int) * th -> int. We substitute with type variables and get: r = ('a -> int) * 'a -> int, which is the compiler output.

Exercise 4 Exercise 6.6 in Mitchell's book fun f(g) = g(g) + 2; 1. The following shows the assignment of type to nodes: (lambda) : r / \ / \ / @ : v / / \ / / \ / @ : u 2 : int + : A @ : t g : tg g : tg where A =def= int->int->-int. 2. Constraints (1) tg = tg -> t (2) int -> (int -> int) = t -> u (3) u = int -> v (4) r = tg -> v 3. Substitution Substituting u = int -> v in (2) we get int -> (int -> int) = t -> (int -> v) from which it follows that t = int and v = int, and thereby r = tg -> int. Now, from equation (1) we have that in order to get tg we must know tg, which has no solution. Hence, the type inference algorithm cannot give an appropriate type to the function ("circularity" error). This can also be seen directly by looking at 1. The compiler outputs: stdin:4.12-4.20 Error: operator is not a function [circularity] operator: 'Z in expression: g g

Exercise 5 Exercise 6.7 in Mitchell's book fun append(nil, l) = l append(x::l,m)=append(l,m); append: ('a list * 'b) => 'b The first argument must be a list of some type. (since nil is the empty list, and x::l must be a list). However we cannot infer anything about the type of the second argument, especially the compiler cannot infer that the argument m is a list, since no list operation/constructor is applied to it; that is why m is given type 'b. If we know that the return type of append is 'b, we know that append does not always return a list which it should if it was defined correctly. Actually, if we call append with a list and some value of type 'b, it just returns the value. Exercise 6 Given the following general signature specifying a type t equipped with the value "zero" and operators "sum", "prod", "diff" and "quo": signature ARITH = sig type t val zero: t val sum: t * t -> t val diff : t * t -> t val prod : t * t -> t val quo : t * t -> t end; Declare a structure "Real" matching signature ARITH, such that Real.t is the type "real" and the components "zero", "sum", etc, denote the corresponding operations on type "real". Answer: structure Real : ARITH = struct type t = real; val zero = 0.0; fun sum (x,y) = x+y : t; fun diff (x,y) = x-y : t; fun prod (x,y) = x*y : t; fun quo (x,y) = x/y : t; end; open Real; sum(2.3,5.9);

Exercise 7 There are two kinds of overloading of functions/operators: context-independent: overloading only done on parameters to function or type of operands for an operator; context-dependent: which operator to use depends also on the type of the result. Hence, with context-independent overloading, the function to be called is solely based upon the type of the actual parameter. With context-dependent overloading, the function to be called may not be identified by the type of the parameters. The context must be taken into account to identify the function to be called. a) Consider the operator ++ (concatenation) to be overloaded, with types Char x Char -> String Char x String -> String String x Char -> String String x String -> String Is this overloading context-independent or context-dependent? Have a look at the following examples: c ++ s (s ++ c) ++ c s ++ (c ++ c) where c is a Char variable and s is a String variable, and identify for each ++ what kind of concatenation it is. c++s: C*S->S (s++c)++c: (S*C->S)*C->S s++(c++c): S*(C*C->S)->S Answer: Context-independent, as all combinations of Char x String are defined.

b) Define in ML four infix operators ++ with the types specified in item a) (in the same order as they are defined). Define then the following four values: val c1 = #"a"; val c2 = #"h"; val s1 = "bcd"; val s2 = "efg"; Before executing, guess what would be the result of the following: c1 ++ c2; => "ah" s1 ++ c2; => "bcdh" c1 ++ s1; => "abcd" s1 ++ s2; => "bcdefg" Try it using sml and explain the result. Answer: infix ++; fun c ++ s = str(c)^s; fun c1 ++ c2 = str(c1)^str(c2); fun s ++ c = s^str(c); fun s1 ++ s2 = s1^s2; c1 ++ c2; s1 ++ c2; c1 ++ s1; s1 ++ s2;

Exercise 8 (NOTE: This exercise is about overloading in general, not in ML!) Consider overloading to be defined for proper procedures (that is, not functions). a) Is it context-dependent or context-independent? independent. "since a procedure does not give a result."??? b) Assume that the operator / is overloaded, with types and int * int -> int int * int -> double. Assume further that we have an overloaded proper procedure "write", the argument of which may be either int or double. Give examples of procedure calls where the procedure to be called cannot be defined uniquely. write(5/9);

Exercise 9 Consider the following parametric function in C++ like syntax: template <typename T> T second(t x, T y) {return y} It is parameterised by the type parameter T, and it returns the value of the second parameter. It is called in this way: int i,j; second<int>(i,j) The <int> is not really needed, as the compiler may infer that the type shall be int, but it is included here for clarity reasons. a) The body of the function does not really use any properties of the type T. Why is it so that C++ still has to generate different code for different actual types? Answer: It will still have to allocate space for x and y as part of the activation record for the call of second, and the space depends upon the type. For example, double usually has size 8, while float has size 4. b) Assume that we had the following version of "second": template <class T> T second(t *x, T *y) {return y} Why would it be possible to use the same code for "second" for different actual classes for T? Answer: Same argument as above, or rather: pointers will take up the same space independently of the class typing the pointer.