Commit b7351597 authored by Dan Grossman's avatar Dan Grossman
Browse files

copy sec04 from spring, but worksheet and slides are in Google Drive

parent 6b1044ae
(* CSE 341, Section 4, Completed/Solution Code *)
(* mutual recursion, just since we haven't shown it to you *)
(* can do any finite state machine this way -- this one checks
for strictly alternating even/odd
mutual recursion is often not tail-recursive, but for
finite state machines it is
*)
let rec start xs =
match xs with
| [] -> true
| i::xs' -> if i mod 2 = 0 then saw_even xs' else saw_odd xs'
and saw_even xs =
match xs with
| [] -> true
| i::xs' -> i mod 2 = 0 && saw_odd xs'
and saw_odd xs =
match xs with
| [] -> true
| i::xs' -> i mod 2 <> 0 && saw_even xs'
(* style above is correct, but we could if we really had to
use first-class functions to encode mutual recursion by
having earlier functions take function arguments and then
calling them with later functions
*)
let saw_even2 f xs =
match xs with
| [] -> true
| i::xs' -> i mod 2 <> 0 && f xs'
let rec saw_odd2 xs =
match xs with
| [] -> true
| i::xs' -> i mod 2 = 0 && saw_even2 saw_odd2 xs'
let start2 xs =
match xs with
| [] -> true
| i::xs' -> if i mod 2 = 0 then saw_even2 saw_odd2 xs' else saw_odd2 xs'
(* module system *)
(* NO CODE CAN DEPEND ON ANYTHING NOT IN THE MODULE TYPE! *)
module type NONEGINT = sig
type t
val mknni : int -> t option
val add : t -> t -> t (* why not t -> t -> int or t -> t -> t option? *)
val mul : t -> t -> t
val sub : t -> t -> t option
val to_int : t -> int (* why not t -> t ? *)
end
module NonNegInt : NONEGINT = struct
type t = int
let mknni i =
if i < 0 then
None
else
Some i
let add a b =
a + b
let mul a b =
a * b (* why not mknni (a * b) ? *)
let sub a b =
mknni (a - b) (* why not a - b ? *)
let to_int a = a (* external world doesn't know this "is it" *)
end
(* we may not have time for this longer example below, but it's
a nice example we might give an overview of
*)
module type NONEMPTYLIST = sig
type 'a t
val single : 'a -> 'a t
val cons : 'a -> 'a t -> 'a t
val tl : 'a t -> 'a t
val hd : 'a t -> 'a
val len : 'a t -> int
val map : ('a -> 'b) -> 'a t -> 'b t
end
module Nel_A : NONEMPTYLIST = struct
type 'a t =
| Single of 'a
| Cons of 'a * 'a t
let single x = Single x
let cons x xs = Cons (x,xs)
let tl xs =
match xs with
| Single _ -> failwith "tl of one-element list"
| Cons(_,xs') -> xs'
let hd xs =
match xs with
| Single x -> x
| Cons(x,_) -> x
let rec len xs =
match xs with
| Single _ -> 1
| Cons(_,xs') -> 1 + len xs'
let rec map f xs =
match xs with
| Single x -> Single (f x)
| Cons (x,xs') -> Cons(f x, map f xs')
end
module Nel_B : NONEMPTYLIST = struct
type 'a t = 'a * ('a list)
let single x = (x,[])
let cons x (y,xs) = (x,y::xs)
let tl xs =
match xs with
| (_,[]) -> failwith "tl of one-element list"
| (_,y::ys) -> (y,ys)
let hd = fst
let len (_,xs') =
1 + List.length xs'
let map f (x,xs') =
(f x, List.map f xs')
end
module Nel_C : NONEMPTYLIST = struct
type 'a t = 'a list
let single x = [x]
let cons x xs = x::xs
let tl xs =
match xs with
| [] -> failwith "impossible -- should never happen"
| x::[] -> failwith "tl of one-element list"
| x::xs' -> xs'
let hd = List.hd
let len = List.length
let map = List.map
end
(* CSE 341, Section 04 *)
(* # Currying *)
(* a) *)
let filter_by_example f x =
List.filter (fun x' -> f x = f x')
(* b) *)
let same_size_as xs = filter_by_example List.length xs
(* “bad style” to avoid the value restriction *)
(* c) *)
(* helper function: takes a string and returns list of its letters*)
let explode str =
let rec exp_helper i cs =
if i < 0 then cs else exp_helper (i - 1) (str.[i]::cs)
in exp_helper (String.length str - 1) []
let count_o s =
List.fold_left (fun acc x -> if x = 'o' then acc + 1 else acc)
0 (explode s)
(* d) *)
let silly_application =
filter_by_example count_o "dogsarecool"
(* e) *)
let contains x =
List.fold_left (fun acc x' -> acc || x' = x) false
(* f) *)
let rec filter_unique f prev xs =
match xs with
| [] -> []
| x'::xs' ->
let result = f x
in if contains result prev
then filter_unique f prev xs'
else x' :: filter_unique f (result :: prev) xs'
(* g) *)
let unique_sums xs = filter_unique List.length [] xs
(* h) *)
let all_that_contain x = (List.filter (contains x))
(* i) *)
let even_only =
List.map (List.filter (fun x -> x mod 2 = 0))
(* j) *)
let even_only_not_empty xs =
List.filter (fun xs' -> xs' <> []) (even_only xs)
(* # Modules *)
(* (a) *)
module type NONEGINT = sig
type t
val mknni : int -> t option
(* why not t -> t -> int or t -> t -> t option? *)
val add : t -> t -> t
val mul : t -> t -> t
val sub : t -> t -> t option
val to_int : t -> int (* why not t -> t ? *)
end
(* (b) *)
module type RATIONAL =
sig
type rational
exception BadFrac
val to_string : rational -> string
val add : rational * rational -> rational
val whole : int -> rational
val make_frac : int * int -> rational
end
module Rational : RATIONAL =
struct
type rational = int * int
exception BadFrac
let to_string (x,y) = "" (* fake body *)
let whole i = (i,1)
let add ((a,b),(c,d)) = (0,0) (* fake body *)
let make_frac (x,y) = (2,2) (* fake body *)
end
(* CSE 341, Section 04 *)
(* # Currying *)
(* Uncomment and fill in the functions below. *)
(* a) *)
(* let filter_by_example *)
(* b) *)
(* let same_size_as *)
(* c) *)
(* let count_o *)
(* d) *)
(* let silly_application *)
(* e) *)
(* let contains *)
(* f) *)
(* let rec filter_unique *)
(* g) *)
(* let unique_sums *)
(* h) *)
(* let all_that_contain *)
(* i) *)
(* let even_only *)
(* j) *)
(* let even_only_not_empty *)
(* # Modules *)
(* (a) *)
module type NONEGINT = sig
(* Your code here *)
end
(* (b) *)
module type RATIONAL =
sig
(* Your code here *)
end
module Rational : RATIONAL =
struct
(* Your code here *)
end
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment