EPITA - Practical Programming 06 - Advanced Module Usage

Similar documents
CMSC 330: Organization of Programming Languages. Basic OCaml Modules

CS3110 Spring 2016 Lecture 6: Modules

Principles of Functional Programming

Lecture 7: The Untyped Lambda Calculus

OCaml Data CMSC 330: Organization of Programming Languages. User Defined Types. Variation: Shapes in Java

CMSC 430 Introduction to Compilers. Fall Everything (else) you always wanted to know about OCaml (but were afraid to ask)

Type structure is a syntactic discipline for maintaining levels of abstraction John Reynolds, Types, Abstraction and Parametric Polymorphism

CMSC 330, Fall 2013, Practice Problems 3

L28: Advanced functional programming

Abstraction. Leo White. February Jane Street 1/ 88

A Short Introduction to OCaml

Reference Cells. Example

Lists. Michael P. Fourman. February 2, 2010

Abstraction Functions and Representation Invariants

Programming Languages and Techniques (CIS120)

Parametricity. Leo White. February Jane Street 1/ 70

CMSC 330: Organization of Programming Languages. Objects and Abstract Data Types

Modules and Representation Invariants

Last time: generic programming

School of Computer Science

Some Advanced ML Features

Signature review: collect declarations

Modules and Abstract Data Types

Lecture 31: Graph Search & Game 10:00 AM, Nov 16, 2018

1 Splay trees. 2 Implementation of splay. CS134b Homework #1 January 8, 2001 Due January 15, 2001

CSE 130, Fall 2005: Final Examination

G Programming Languages - Fall 2012

CSE 130, Fall 2006: Final Examination

Modular Programming. Prof. Clarkson Fall Today s music: "Giorgio By Moroder" by Daft Punk

Life in a Post-Functional World

CS Lectures 2-3. Introduction to OCaml. Polyvios Pratikakis

Sample Exam; Solutions

CMSC 330, Fall 2013, Practice Problem 3 Solutions

CSCI 2041: First Class Functions

Programming Languages and Techniques (CIS120)

CS Lecture 14: Hash tables. Prof. Clarkson Spring Today s music: Re-hash by Gorillaz

Two approaches to writing interfaces

Pattern Matching and Abstract Data Types

CS 11 Ocaml track: lecture 4. Today: modules

Derek Dreyer. WG2.8 Meeting, Iceland July 16-20, 2007

CS558 Programming Languages

Introduction to OCaml

Runtime types

F-ing Applicative Functors

Outline. Introduction Concepts and terminology The case for static typing. Implementing a static type system Basic typing relations Adding context

CIS 120 Midterm I February 16, 2015 SOLUTIONS

CIS 120 Midterm I October 2, Name (printed): Username (login id):

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

Modular Module Systems: a survey

Introduction to ML. Mooly Sagiv. Cornell CS 3110 Data Structures and Functional Programming

Modular implicits for OCaml how to assert success. Gallium Seminar,

CMSC 330: Organization of Programming Languages

Abram Hindle Kitchener Waterloo Perl Monger October 19, 2006

CSE 341 Section 5. Winter 2018

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

CSCI-GA Scripting Languages

Programming in Standard ML: Continued

ML Type Inference and Unification. Arlen Cox

CMSC 330: Organization of Programming Languages. OCaml Imperative Programming

Typed Racket: Racket with Static Types

Cornell University 12 Oct Solutions. (a) [9 pts] For each of the 3 functions below, pick an appropriate type for it from the list below.

CIS 120 Final Exam May 7, Name (printed): Pennkey (login id):

The Typed Racket Guide

Programming Languages and Techniques (CIS120)

SNU Programming Language Theory

A Fourth Look At ML. Chapter Eleven Modern Programming Languages, 2nd ed. 1

Mutation. COS 326 David Walker Princeton University

CSC/MAT-220: Lab 6. Due: 11/26/2018

Programming Languages and Techniques (CIS120e)

Programming Languages and Techniques (CIS120)

Substructural Typestates

Types, Semantics, and Programming Languages (IK3620)

CMSC 330: Organization of Programming Languages. OCaml Imperative Programming

Introduction to ML. Mooly Sagiv. Cornell CS 3110 Data Structures and Functional Programming

L3 Programming September 19, OCaml Cheatsheet

Introduction to ML. Mooly Sagiv. Cornell CS 3110 Data Structures and Functional Programming

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

SML Style Guide. Last Revised: 31st August 2011

CMSC 631. Functional Programming with OCaml

FUNCTIONAL PROGRAMMING NO.9 TYPE AND CLASS. Tatsuya Hagino

Lecture 19: Signatures, Structures, and Type Abstraction

Whidbey Enhancements to C# Jeff Vaughan MSBuild Team July 21, 2004

Notes on specifying user defined types

CS153: Compilers Lecture 14: Type Checking

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

TYPE INFERENCE. François Pottier. The Programming Languages Mentoring ICFP August 30, 2015

CSE341: Programming Languages Lecture 11 Type Inference. Dan Grossman Spring 2016

Topics Covered Thus Far CMSC 330: Organization of Programming Languages

Parametric types. map: ( a (a b) a list b list. filter: ( a bool) a list a list. Why? a and b are type variables!

Programming Languages and Techniques (CIS120)

Metaprogramming assignment 3

Types, Type Inference and Unification

Overloading, Type Classes, and Algebraic Datatypes

The Typed Racket Reference

Introduction to Delimited Continuations. Typing Printf. Printf. Kenichi Asai. Ochanomizu University. April 13, 2008

Specification and Verification in Higher Order Logic

ECE 449 OOP and Computer Simulation Lecture 12 Resource Management II

Type Hierarchy. Comp-303 : Programming Techniques Lecture 9. Alexandre Denault Computer Science McGill University Winter 2004

COEN244: Class & function templates

G Programming Languages Spring 2010 Lecture 8. Robert Grimm, New York University

Transcription:

More EPITA - Practical Programming 06 - Advanced Module Usage marwan.burelle@lse.epita.fr http://wiki-prog.infoprepa.epita.fr

Outline More 1 Embedded Declaring Module Types 2 Data Structures And Code Safety Opaque Types More Advanced Stuff 3 Playing Around Signature

More Embedded Declaring Module Types

Module Sublanguage More Embedded Declaring Module Types are not only usable at file level OCaml provides a sublanguage dedicated to modules One is able to build embedded modules, describe module interfaces or construct function over modules.

Overview More 1 Embedded Declaring Module Types Embedded Declaring Module Types

Building Local Module Embedded module Vector = struct type a t = { capacity : int; mutable size : int; tab : a array; } let make sz = { capacity = sz; size = 0; tab = Array.make sz (Obj.magic None) } let add v x = if v.size < v.capacity then begin v.tab.(v.size) <- x; v.size <- v.size + 1; end end More Embedded Declaring Module Types let v = Vector.make 10

Accessing Embedded (* module: a.ml *) module B = struct type t = int let compare a b = a - b end a.ml c.ml (* module: c.ml *) type t = A.B.t list let empty : t = [] let rec insert x = function (h::_) as l when A.B.compare x h = 0 -> l h::t when A.B.compare x h > 0 -> h :: insert x t l -> x :: l More Embedded Declaring Module Types

Overview More 1 Embedded Declaring Module Types Embedded Declaring Module Types

Embedded Module And Interface Minimal Set module type MinSetType = sig type a t (* Create an empty set *) val create : unit -> a t (* Test for emptyness *) val is_empty : a t -> bool (* Add an element *) val add : a t -> a -> unit (* Extract min value *) val take_min : a t -> a end Minimal Set module DummSet: MinSetType = struct type a t = { mutable l : a list; } let create () = {l = []} let is_empty s = s.l = [] let add s x = s.l<-x::s.l let take_min s = match List.sort compare s.l with [] -> raise Not_found h::t -> s.l <- t; h end More Embedded Declaring Module Types

Direct Interface Assignment More Typed Module module A : sig type t val compare : t -> t -> int end = struct type t = int let compare a b = Pervasives.compare a b end Embedded Declaring Module Types

Affecting Types To Existing More Forcing Types module OrderedStr : sig type t val compare : t -> t -> int end = String Embedded Declaring Module Types The existing module must provide declared symbols The new module will only provide declared symbols

More Data Structures And Code Safety Opaque Types More Advanced Stuff

Overview More 2 Data Structures And Code Safety Opaque Types More Advanced Stuff Data Structures And Code Safety Opaque Types More Advanced Stuff

Quick n Dirty Ordered Set Module set.ml type a t = a list let empty = [] let is_empty s = s = [] let rec add s = function (h::_) as l when h = s -> l h::t when h < s -> h :: add s t l -> s::l let rec mem x = function [] -> false h::t when h <= x -> x=h mem x t _ -> false let rec union s1 s2 = match (s1,s2) with ([],s) (s,[]) -> s (h1::t1, h2::_) when h1 < h2 -> h1 :: union t1 s2 (h1::_, h2::t2) when h1 > h2 -> h2 :: union s1 t2 (h1::t1, _::t2) -> h1 :: union t1 t2 More Data Structures And Code Safety Opaque Types More Advanced Stuff

Is This Module Safe? More An ordered set must verify two properties: It must be sorted It must not contain twice the same element Take a look at function add x s: if s is a correct set then: x will be added, to its right place, only if it is not in s In any case, the output set will be correct. Data Structures And Code Safety Opaque Types More Advanced Stuff If the input set is not correct, we can t guaranteed the correctness of the output. union has the same properties, and, of course, mem can only provide a correct answer if its input is a correct set.

Unsafe scenario More Unsafe use of set let myset = [1;2;4;3] let myset2 = add 3 myset Evaluation output val myset2 : int list = [1; 2; 3; 4; 3] Data Structures And Code Safety Opaque Types More Advanced Stuff The result is not a correct set, as expected.

Solutions? More Verifies properties when entering set operations: too expensive Manually check all usage of set operations: unrealistic and unsafe Enforce that only values built using Set operations are used: Probably the good solutions... Data Structures And Code Safety Opaque Types More Advanced Stuff

Overview More 2 Data Structures And Code Safety Opaque Types More Advanced Stuff Data Structures And Code Safety Opaque Types More Advanced Stuff

Hiding More If we re able to hide the fact that sets are lists, we won t be able to provide ill-formed values to set operations. That s the purpose of opaque types! set.mli type a t (* no implem *) Data Structures And Code Safety Opaque Types More Advanced Stuff val empty : a t val is_empty : a t -> bool val add : a -> a t -> a t val mem : a -> a t -> bool val union : a t -> a t -> a t

Hiding wrong.ml let main () = let l = [1;2;4;3] in let l2 = Set.add 3 l in () (* Nothing to do *) let _ = main () File "wrong.ml", line 3, characters 21-22: Error: This expression has type int list but an expression was expected of type int Set.t More Data Structures And Code Safety Opaque Types More Advanced Stuff We finaly get what we want, only value constructed by the module operations are usable!

More On Opaque Types More Enforce loose coopling: we can completely rewrite the module implementation without rewriting the code using it. With a good naming convention, data usage are more clear and self-explaining. Of course, nothing is perfect: We can t extend the module easily The module must provide all the possible operations requiring access to the inner representation. Data Structures And Code Safety Opaque Types More Advanced Stuff

Multi-Level Opacity mixed.ml module T = struct type a t = a list let empty = [] let is_empty s = s = [] let rec add s = function (h::_) as l when h = s -> l h::t when h < s -> h :: add s t l -> s::l end let set_factory n = let rec aux a = function 0 -> a n -> aux (n::a) (n-1) in aux [] n More Data Structures And Code Safety Opaque Types More Advanced Stuff mixed.mli module T : sig type a t val empty : a list val is_empty : a list -> bool val add : a -> a list -> a list end val set_factory : int -> int T.t

Overview More 2 Data Structures And Code Safety Opaque Types More Advanced Stuff Data Structures And Code Safety Opaque Types More Advanced Stuff

Phantom Types: Ref Types More Ref module Ref : sig type t val create : int -> t val set : t -> int -> unit val get : t -> int end = struct type t = int ref let create x = ref x let set t x = t := x let get t =!t end Data Structures And Code Safety Opaque Types More Advanced Stuff

Phantom Types: Building Read-Only Ref RO-Ref type readonly type readwrite module PRef : sig type a t val create : int -> readwrite t val set : readwrite t -> int -> unit val get : a t -> int val readonly : a t -> readonly t end = struct type a t = Ref.t let create = Ref.create let set = Ref.set let get = Ref.get let readonly x = x end More Data Structures And Code Safety Opaque Types More Advanced Stuff

Phantom Types More Trying let sumrefs reflist = List.fold_left (+) 0 (List.map PRef.get reflist) let increfs reflist = List.iter (fun r -> PRef.set r (PRef.get r + 1)) reflist Data Structures And Code Safety Opaque Types More Advanced Stuff Typing val sumrefs : a PRef.t list -> int val increfs : readwrite PRef.t list -> unit

More Playing Around Signature

Overview More 3 Playing Around Signature Playing Around Signature

Set With Parametric Order More Using default ordering is not always convenient, and even somtimes not possible (like objects.) The usual solution is to provide a comparison function. set.ml type a t = a list let empty = [] let is_empty s = s = [] let rec add cmp s = function (h::_) as l when cmp h s = 0 -> l h::t when cmp h s < 0 -> h :: add cmp s t l -> s::l let rec mem cmp x = function [] -> false h::t when cmp h x <= 0 -> cmp x h = 0 mem cmp x t _ -> false Playing Around Signature

Using Higher Order Parameter More The issue with the previous solution is that we need to pass the comparison function to all operations. Even if we use an opaque type, we may break the data structure by providing different comparison functions. Playing Around Signature fail! let s = Set.add (fun a b -> a - b) 1 ( Set.add (fun a b -> b - a) 2 Set.empty )

Overview More 3 Playing Around Signature Playing Around Signature

Poor Man Polymorphism More trickyset.ml module T = (* Put your module here *) type t = T.t list let empty = [] let is_empty s = s = [] let rec add s = function (h::_) as l when T.compare h s = 0 -> l h::t when T.compare h s < 0 -> h :: add s t l -> s::l let rec mem x = function [] -> false h::t when T.compare h x <= 0 -> T.compare x h = 0 mem x t _ -> false Playing Around Signature

Module As Parameter? More In the previous example, we build our module based on the existence of a module T providing what we need. The issue is that we need to copy and modify this module to build another version. What if T was a parameter to a function from module to module? Playing Around Signature This is the idea of functor: a function from modules to module

Building A Functor More We need to fix the type of the parameter. We ll define a module signature for that and then define the functor: set.ml (* Module Type of the parameter *) module type OrderedType = sig type t val compare: t -> t -> int end (* Defining The Functor *) module Make (T:OrderedType) = struct type t = T.t list (*... *) end Playing Around Signature

Functor s Code set.ml module Make (T:OrderedType) = struct type t = T.t list let empty = [] let is_empty s = s = [] let rec add s = function (h::_) as l when T.compare h s = 0 -> l h::t when T.compare h s < 0 -> h :: add s t l -> s::l let rec mem x = function [] -> false h::t when T.compare h x <= 0 -> T.compare x h = 0 mem x t _ -> false end More Playing Around Signature

Using Our Functor More Set of int module Int = struct type t = int let compare a b = Pervasives.compare a b end Playing Around Signature module IntSet = Set.Make(Int)

Functor Instantiation Is A Module More Type of our functor module IntSet : sig type t = Int.t list val empty : a list val is_empty : a list -> bool val add : Int.t -> Int.t list -> Int.t list val mem : Int.t -> Int.t list -> bool end Playing Around Signature

Overview More 3 Playing Around Signature Playing Around Signature

Functor s Signature More Using.mli file set.mli module type OrderedType = sig type t val compare : t -> t -> int end Playing Around Signature module Make : functor (T : OrderedType) -> sig type t = T.t list val empty : t val is_empty : t -> bool val add : T.t -> t -> t val mem : T.t -> t -> bool end

And Opaque Types More You can rewrite the signature with an opaque version for the type t This form will prevent usage of ill-formed set. It also protect us from mixing containers built on the same type but with different comparison functions. Playing Around Signature

Set Of String strset.ml module Str = struct type t = string let compare a b = compare (String.lowercase a) (String.lowercase b) end module NoCaseStrSet = Set.Make(Str) module CaseStrSet = Set.Make(String) More Playing Around Signature let s = NoCaseStrSet.add "Aa" ( CaseStrSet.add "AA" ( CaseStrSet.add "aa" CaseStrSet.empty ) )

Functor s Signature More Using module signature set.ml module type S = sig type content type t val empty : t val is_empty : t -> bool val add : content -> t -> t val mem : content -> t -> bool end module Make (T:OrderedType) = struct type content = T.t type t = content list (*... *) end Playing Around Signature

Functor s Signature More Using module signature set.mli module type S = sig type content type t val empty : t val is_empty : t -> bool val add : content -> t -> t val mem : content -> t -> bool end module Make (T : OrderedType) : S Playing Around Signature

Functor s Signature More The previous solution as a major drawback... Too bad module StrSet = Set.Make(String) Playing Around Signature let s = StrSet.add "aa" StrSet.empty Error: This expression has type string but an expression was expected of type StrSet.content = Set.Make(String).content

Functor s Signature More Using module signature (this one is working... ) set.mli module type S = sig type content type t val empty : t val is_empty : t -> bool val add : content -> t -> t val mem : content -> t -> bool end module Make (T : OrderedType) : S with type content = T.t Playing Around Signature