CSCI 330: Folding in OCaml
Goals
- to continue our journey with OCaml
- to gain hands-on experience with folding and other
List
operations - to add really, really big numbers :)
Overview
You have been tasked with implementing several functions in OCaml. All of the programs require relatively little coding ranging from 2 to 15 lines. If any function requires more than that, you will need to rethink your solution.
- Download the handout file from Autolab
- Update each of the functions with your own solutions. As a reminder, you are expected to complete this individually.
- Test your program using the OCaml environment installed on the Linux Lab machines
- Submit your updated handout file to the “Folding” Autolab assignment.
Start this assignment early I cannot emphasize this enough! ML programming is relatively easy (syntax-wise) but it will seem foreign, especially with recursion and list manipulation.
Note: Solutions using imperative features such as references, arrays, or while loops will receive no credit. Do not use any additional libraries, just use standard OCaml as installed in the Linux environment.
sqsum
(10 points)
Fill in the appropriate values for (1) the folding function,
f
, and (2) the base case value.
Takes a list of integers [x1;...;xn]
as input
Returns an integer representing \(\sum_{i=1}^{n}x_i^2\)
Signature:
int list -> int
Expected Output
sqsum [];;(* int = 0 *)
1;2;3;4] ;;
sqsum [(* int = 30 *)
-1;-2;-3;-4] ;;
sqsum [(* int = 30 *)
sepConcat
(15 points)
Fill in the appropriate values for (1) the folding function,
f
, (2) the base value, base
, and (3) the list,
l
.
This is a curried function which accepts a string separator
sep
and a list of string
s
[s1;...;sn]
- If there are zero strings in the list
""
should be returned - If there is one string in the list, then
s1
should be returned - Otherwise, the concatenation of
s1 sep s2 sep ... sep sn
should be returned.
Signature
string -> string list -> string
Expected Output
", " ["foo";"bar";"baz"];;
sepConcat (* string = "foo, bar, baz" *)
"---" [];;
sepConcat (* string = "" *)
"," ["hello"];;
sepConcat (* string = "hello" *)
"" ["a";"b";"c"];;
sepConcat (* string = "abc" *)
stringOfList
(5 points)
Using a single expression/line (with
List.map
and sepConcat
), implement a function
which prints a string representation of a list.
This is a curried function which accepts a function, f
,
which converts the underlying type of the list to a string
(e.g. string_of_int
for int list
) as well as a
list, l
.
If our list contains the elements [l1;l2;...;ln]
you can
imagine the functional equivalence being:
"[" (f l1) "; " (f l2) "; " ... "; " (f ln) "]"
Signature
string) -> 'a list -> string ('a ->
Expected Output
string_of_int [1;2;3;4;5;6];;
stringOfList (* string = "[1; 2; 3; 4; 5; 6]" *)
fun x -> x) ["foo"];;
stringOfList ((* string = "[foo]" *)
string_of_int) [[1;2;3];[4;5];[6];[]];;
stringOfList (stringOfList (* string = "[[1; 2; 3]; [4; 5]; [6]; []]" *)
pipe
(10 points)
The function pipe takes a list of functions [f1;...;fn]
and returns a function f
such that for any x
,
the application f x
returns the result
fn(...(f2(f1 x)))
. Again, your task is to fill in the
appropriate values for (1) the folding function f
and (2)
the base case base
.
Signature
list -> 'a -> 'a ('a -> 'a)
Expected Output
3;;
pipe [] (* int = 3 *)
fun x-> 2*x);(fun x -> x + 3)] 3;;
pipe [((* int = 9 *)
fun x -> x + 3);(fun x-> 2*x)] 3;;
pipe [((* int = 12 *)
pipec
(10 points)
Fill in the skeleton given for pipec
, which has the same
behavior as pipe
above BUT uses function currying. In this
version of the function, you will not explicitly take in the second
parameter. Instead you will return a function that expects this
parameter and uses it when it is received.
Signature
list -> ('a -> 'a) ('a -> 'a)
Expected Output
3;;
pipec [] (* int = 3 *)
fun x-> 2*x);(fun x -> x + 3)] 3;;
pipec [((* int = 9 *)
fun x -> x + 3);(fun x-> 2*x)] 3;;
pipec [((* int = 12 *)
prodLists
(10 points)
The function prodLists takes two lists of integers
[x1;...;xn]
and [y1;...;yn
(you can assume
that they’re the same length) and returns a list of integers with the
product of each pair of numbers [x1*y1;...;xn*yn]
. Your
task is to fill in the appropriate values for (1) the folding function
f
(2) the base case base
and (3) the args
being passed to List.fold_left
. Hint: Look at using
List.combine
.
Signature
int list -> int list -> int list
Expected Output
prodLists [] [];;(* int list = [] *)
3] [4];;
prodLists [(* int list = [12] *)
10; 20; 30] [5; 5; 5];;
prodLists [(* int list = [50; 100; 150] *)
bigAdd
(20 points)
As you may have noticed, the OCaml type int only contains values up to a certain size. For example, entering 99999999999999999999 results in the message “Integer literal exceeds the range of representable integers of type int”. This problem involves implementing functions to manipulate large numbers represented as lists of integers.
Several helper functions (clone
, padZero
,
removeZero
) have been included in the handout file. Use
these in your implementations wherever they are helpful. Each integer
will be in the range [0..9] and returns the list corresponding to the
addition of the two big integers.
Again, you have to fill in the implementation to supply the
appropriate values to f
, base
, and
args
. One of the keys here is to realize that your
accumulator can carry more than one piece of data. WARNING: this
problem is significantly harder than the other problems
Signature
int list -> int list -> int list
Expected Output
9;9] [1;0;0;2];;
bigAdd [(* int list = [1;1;0;1] *)
9;9;9;9] [9;9;9];;
bigAdd [(* int list = [1;0;9;9;8] *)
bigMul
and mulByDigit
(20 points extra credit)
Next you will write functions to multiply two big integers.
Signature
mulByDigit
has a type signature of:int -> int list -> int list
bigMul
has a type signature of:int list -> int list -> int list
Expected Output
9 [9;9;9;9];;
mulByDigit (* int list = [8;9;9;9;1] *)
9;9;9;9] [9;9;9;9];;
bigMul [(* int list = [9;9;9;8;0;0;0;1] *)
9;9;9;9;9] [9;9;9;9;9];;
bigMul [(* int list = [9;9;9;9;8;0;0;0;0;1] *)
Submission
Submit folding.ml
to the “Folding” assignment through Autolab
NOTE: Autolab will not detect it if you alter the templates. However, the specs for the assignment say that you must use the templates as they appear in the handout. I will be reviewing code and deducting the points for any problems where the template has been altered!
Grading
90 points total
- 80 points on passing the autolab tests
- 10 points on documentation, formatting, describing what your code does, style, and adhering to the specifications and instructions listed
- Up to 20 points of extra credit
- NOTE points may be adjusted on the autograded component if you do not match the appropriate style/implementation requirements.
Attribution
This assignment was adapted from Sorin Lerner’s CSE 130 course at UCSD and slightly modified by Dr. Schwartz, Prof. Killian, and Dr. Zoppetti