Advertisement
justin_hanekom

Ocaml prelude

Jul 20th, 2016
316
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
OCaml 24.54 KB | None | 0 0
  1. (*
  2.  * File: prelude.ml
  3.  * Copyright (c) 2018 Justin Hanekom <justin_hanekom@yahoo.com>
  4.  *)
  5.  
  6. (*
  7.  * Permission is hereby granted, free of charge, to any person obtaining a
  8.  * copy of this software and associated documentation files (the "Software"),
  9.  * to deal in the Software without restriction, including without limitation
  10.  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  11.  * and/or sell copies of the Software, and to permit persons to whom the
  12.  * Software is furnished to do so, subject to the following conditions:
  13.  *
  14.  * The above copyright notice and this permission notice shall be included in
  15.  * all copies or substantial portions of the Software.
  16.  *
  17.  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  18.  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  19.  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
  20.  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  21.  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  22.  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  23.  * DEALINGS IN THE SOFTWARE.
  24.  *)
  25.  
  26. open List
  27. open Printf
  28. open String
  29.  
  30. (* ----- TUPLES ----- *)
  31.  
  32. (** Returns the first component of a pair. *)
  33. let fst (a, _) = a
  34.  
  35. (** Returns the second component of pair. *)
  36. let snd (_, b) = b
  37.  
  38.  
  39. (* ----- FOLDS AND TRAVERSALS ----- *)
  40.  
  41. (**
  42.  * Left-associative fold of a list.
  43.  * This function is not tail recursive.
  44.  *
  45.  * @param fn  function to apply to  each element of the list;
  46.  *            fn is called with the accumulator and an element,
  47.  *            and must return a new accumulator
  48.  * @param acc initial accumulator value
  49.  * @param lst list of elements to be fed to f
  50.  * @result    final accumulator value created by applying f
  51.  *            to each element of xs, from the left
  52.  * @see       fold_left
  53.  *)
  54. let foldl fn acc lst = fold_left fn acc lst
  55.  
  56. (**
  57.  * Right-associative fold of a list.
  58.  * This function is tail recursive.
  59.  *
  60.  * @param fn  function to apply to each element of the list;
  61.  *            fn is called with the accumulator and an element,
  62.  *            and must return a new accumulator
  63.  * @param acc initial accumulator value
  64.  * @param lst list of elements to be fed to f
  65.  * @result    final accumulator value created by applying f
  66.  *            to each element of xs, from the right
  67.  * @see       fold_right
  68.  *)
  69. let foldr fn lst acc = fold_right fn lst acc
  70.  
  71. (**
  72.  * Maps each element of a list to a function, and combines the results.
  73.  * This function is not tail recursive.
  74.  *
  75.  * @param fn  function to apply to each element of the list
  76.  * @param lst list of elements to be fed to f
  77.  * @result    new list of the form [f l1; f l2; f l3; ...]
  78.  * @see       map
  79.  *)
  80. let map fn lst = List.map fn lst
  81.  
  82. (**
  83.  * Maps each element of a list to a function, and throws away the results.
  84.  * This function is not tail recursive.
  85.  *
  86.  * @param fn  function to apply to each element of the list
  87.  * @param lst list of elements to be fed to f
  88.  * @see       List.iter
  89.  *)
  90. let map_ fn lst = List.iter fn lst
  91.  
  92. (**
  93.  * Returns the last element of a list, which must be non-empty.
  94.  * This function is tail-recursive.
  95.  *
  96.  * @param lst list to get the last element of
  97.  * @see       first
  98.  *)
  99. let rec last lst = match lst with
  100.     | x::[] -> x
  101.     | x::xs -> last xs
  102.     | _     -> failwith "last []"
  103.  
  104. (**
  105.  * Returns all elements excepting the last of a list,
  106.  * which must be non-empty.
  107.  * This function is not tail-recursive.
  108.  *
  109.  * @param lst list from which to extract the initial elements
  110.  * @see       tail
  111.  *)
  112. let rec init lst = match lst with
  113.     | x::[] -> []
  114.     | x::xs -> x::init xs
  115.     | _     -> failwith "init []"
  116.  
  117. (**
  118.  * Left-associative fold of a list, which must be non-empty.
  119.  * The first element of the list is used as the initial accumulator value.
  120.  * This function is not tail recursive.
  121.  *
  122.  * @param fn  function to apply to each element of the list;
  123.  *            fn is called with the accumulator and an element,
  124.  *            and must return a new accumulator
  125.  * @param lst list of elements to be fed to f
  126.  * @see       foldl
  127.  * @see       fold_left
  128.  * @see       foldr'
  129.  *)
  130. let foldl' fn lst = match lst with
  131.     | x::xs -> fold_left fn x xs
  132.     | _     -> failwith "foldl' []"
  133.  
  134. (**
  135.  * Right-associative fold of a list, which must be non-empty.
  136.  * The last element of the list is used as the initial accumulator value.
  137.  * This function is tail recursive.
  138.  *
  139.  * @param fn  function to apply to each element of the list, from the right;
  140.  *            fn is called with the accumulator and an element,
  141.  *            and must return a new accumulator
  142.  * @param lst list of elements to be fed to f
  143.  * @see       foldr
  144.  * @see       fold_right
  145.  * @see       foldl'
  146.  *)
  147. let foldr' fn lst = match lst with
  148.     | _::_ -> let acc = init lst
  149.               and lst' = last lst in
  150.               fold_right fn acc lst'
  151.     | _    -> failwith "foldr' []"
  152.  
  153.  
  154. (* -----  LIST OPERATIONS ----- *)
  155.  
  156. (** Returns whether or not a list is empty. *)
  157. let null lst = match lst with
  158.     | [] -> true
  159.     | _  -> false
  160.  
  161. (** Returns the length of a list. *)
  162. let length = List.length
  163.  
  164. (** Returns the first element of a list, which must be non-empty. *)
  165. let head lst = match lst with
  166.     | _::_ -> List.hd lst
  167.     | []   -> failwith "head []"
  168.  
  169. (** Returns the remaining elements of a list, which must be non-empty. *)
  170. let tail lst = match lst with
  171.     | _::_ -> List.tl lst
  172.     | []   -> failwith "tail []"
  173.  
  174. (** Returns a copy of a list, with the elements in reverse order. *)
  175. let reverse = List.rev
  176.  
  177. (** Appends two lists .*)
  178. let (++) lst1 lst2  = append lst1 lst2
  179.  
  180. (**
  181.  * Equivalent to `(reverse lst1) ++ lst2`,
  182.  * but tail recursive and more efficient.
  183.  *
  184.  * @see reverse
  185.  * @see (++)
  186.  * @see append
  187.  *)
  188. let reverse_append lst1 lst2 = List.rev_append lst1 lst2
  189.  
  190. (**
  191.  * Concatenates a list of lists.
  192.  *
  193.  * @param xss a list of lists of the form [[]; []; ...]
  194.  *)
  195. let concat xss = List.concat xss
  196.  
  197. (**
  198.  * Returns a number of elements from the beginning of a list.
  199.  * This function is not tail-recursive.
  200.  *
  201.  * @param num number of items to take from the list
  202.  * @param lst list from which to take elements from the left of
  203.  * @see       drop
  204.  *)
  205. let rec take num lst =
  206.     if num <= 0 || (null lst)
  207.     then []
  208.     else head lst::take (num-1) (tail lst)
  209.  
  210. (**
  211.  * Drops a number of elements from the beginning of a list.
  212.  * This function is tail-recursive.
  213.  *
  214.  * @param num the number of elements to drop from the list
  215.  * @param lst list from which to drop elements
  216.  * @result    a list that is the list lst with the first num elements removed
  217.  * @see       @take
  218.  *)
  219. let rec drop num lst =
  220.     if num <= 0
  221.     then lst
  222.     else drop (num-1) (tail lst)
  223.  
  224. (**
  225.  * Returns the biggest element of a list, which must be non-empty.
  226.  *
  227.  * @see minimum
  228.  *)
  229. let maximum lst = match lst with
  230.     | _::_ -> foldl' (fun a b -> max a b) lst
  231.     | _    -> failwith "maximum []"
  232.  
  233. (**
  234.  * Returns the smallest element of a list, which must be non-empty.
  235.  *
  236.  * @see maximum
  237.  *)
  238. let minimum lst = match lst with
  239.     | _::_ -> foldl' (fun a b -> min a b) lst
  240.     | _    -> failwith "minimum []"
  241.  
  242. (**
  243.  * Returns the sum of a list of integers, which must be non-empty.
  244.  *
  245.  * @see product
  246.  *)
  247. let sum lst = match lst with
  248.     | _::_ -> foldl' (fun a b -> a+b) lst
  249.     | _    -> failwith "sum []"
  250.  
  251. (**
  252.  * Returns the product of a list of integers, which must be non-empty.
  253.  *
  254.  * @see sum
  255.  *)
  256. let product lst = match lst with
  257.     | _::_ -> foldl' (fun a b -> a*b) lst
  258.     | _    -> failwith "product []"
  259.  
  260. (**
  261.  * Returns whether or not an element is in a list.
  262.  * This function is tail-recursive.
  263.  *
  264.  * @param x   the element to search for
  265.  * @param lst the list in which to search for the element x
  266.  * @result    true if x is found in the list lst, otherwise false
  267.  *)
  268. let rec elem x lst = match lst with
  269.     | y::ys -> if x = y
  270.                then true
  271.                else elem x ys;
  272.     | []    -> false
  273.  
  274.  
  275. (* ----- NUMERIC FUNCTIONS ----- *)
  276.  
  277. (** Returns the negative of an integer. *)
  278. let negate n = (-n)
  279.  
  280. (** Returns whether or not an integer is even. *)
  281. let even n = n mod 2 = 0
  282.  
  283. (** Returns whether or not an integer is odd. *)
  284. let odd n = n mod 2 != 0
  285.  
  286. (** Returns the sign of an integer, either 1 or -1. *)
  287. let signum n = if n >= 0 then 1 else (-1)
  288.  
  289. (**
  290.  * Returns the greatest common divisor of two integers.
  291.  * This function is tail-recursive.
  292.  *)
  293. let gcd a b =
  294.    let rec gcd' a b = if b = 0
  295.                        then a
  296.                        else gcd' b (a mod b) in
  297.     gcd' (abs a) (abs b)
  298.  
  299. (** Returns the smallest positive integer that two integers divide by. *)
  300. let lcm a b = match (a, b) with
  301.     | (_, 0) -> 0
  302.     | (0, _) -> 0
  303.     | (a, b) -> (abs a*b) / (gcd a b)
  304.  
  305.  
  306. (* ----- STRING OPERATIONS ----- *)
  307.  
  308. (** Returns whether or not the string is empty. *)
  309. let is_empty str = str = ""
  310.  
  311. (** Compares two strings, ignoring case. *)
  312. let compare_ignore_case str1 str2 =
  313.     let lower1 = lowercase str1
  314.     and lower2 = lowercase str2 in
  315.     compare lower1 lower2
  316.  
  317. (**
  318.  * Returns whether or not two strings are equal, ignoring case.
  319.  *
  320.  * @see compare_ignore_case
  321.  *)
  322. let equals_ignore_case str1 str2 = compare_ignore_case str1 str2 = 0
  323.  
  324. (**
  325.  * Returns whether or not one string begins with another.
  326.  *
  327.  * @param prefix prefix to be searched for in str
  328.  * @param str    string to be tested if it begins with prefix
  329.  * @result       true if str begins with prefix, otherwise false
  330.  * @see          ends_with
  331.  *)
  332. let begins_with prefix str =
  333.     let str_len = String.length str
  334.     and pref_len = String.length prefix in
  335.     if str_len < pref_len
  336.     then false
  337.     else String.sub str 0 pref_len = prefix
  338.  
  339. (**
  340.  * Returns whether or not one string ends with another.
  341.  *
  342.  * @param suffix suffix to be searched for in str
  343.  * @param str    string to be tested if it ends with suffix
  344.  * @result       true if str ends with suffix, otherwise false
  345.  * @see          begins_with
  346.  *)
  347. let ends_with suffix str =
  348.     let str_len = String.length str
  349.     and suff_len = String.length suffix in
  350.     let pos = str_len-suff_len in
  351.     if str_len < suff_len
  352.     then false
  353.     else String.sub str pos suff_len = suffix
  354.  
  355. (**
  356.  * Returns whether or not the string contains the substring.
  357.  * This function is tail-recursive.
  358.  *
  359.  * @param substr substring to search for in the string
  360.  * @param str    string to be searched for the substring
  361.  * @result       true if the string contains the substring, otherwise false
  362.  *)
  363. let rec contains_substring substr str = match str with
  364.     | "" -> false
  365.     | _  -> if begins_with substr str
  366.             then true
  367.             else
  368.                 let str_len = (String.length str)-1 in
  369.                 let new_str = String.sub str 1 str_len in
  370.                 contains_substring substr new_str
  371.  
  372. (**
  373.  * Returns the index within the string of the character ch.
  374.  * Throws Not_found if the character does not occur in the string.
  375.  *
  376.  * @param ch  character to search for in the string
  377.  * @param str string to search for the character ch
  378.  * @result    index of the first position where ch occurs in str
  379.  * @see       index_of
  380.  * @see       last_index_of_char
  381.  *)
  382. let index_of_char ch str = index str ch
  383.  
  384. (**
  385.  * Returns the index within the string str of the string substr.
  386.  * Throws Not_found if the string does not occur in the string str.
  387.  * This function is tail-recursive.
  388.  *
  389.  * @param substr string to search for in the string str
  390.  * @param str    string to search for the string substr
  391.  * @result       index of the first position where substr occurs in str
  392.  * @see          index_of_char
  393.  * @see          last_index_of
  394.  *)
  395. let index_of substr str =
  396.     if substr = ""
  397.     then 0
  398.     else
  399.         let ch = substr.[0] in
  400.         let rec fn from =
  401.             let i = index_from str from ch in
  402.             let sub_len = String.length substr in
  403.             let found = String.sub str i sub_len in
  404.             if found = substr
  405.             then i
  406.             else fn (i+1) in
  407.         fn 0
  408.  
  409. (**
  410.  * Returns the last index within the string of the character ch.
  411.  * Throws Not_found if the character does not occur in the string.
  412.  *
  413.  * @param ch  character to search for in the string
  414.  * @param str string to search for the character ch
  415.  * @result    index of the last position where ch occurs in the string
  416.  * @see       index_of_char
  417.  * @see       last_index_of
  418.  *)
  419. let last_index_of_char ch str = rindex str ch
  420.  
  421. (**
  422.  * Returns the last index within the string str of the string substr.
  423.  * Throws Not_found if the string does not occur in the string str.
  424.  * This function is tail-recursive.
  425.  *
  426.  * @param substr string to search for in the string str
  427.  * @param str    string to search for the string substr
  428.  * @result       index of the last position where substr occurs in str
  429.  * @see          index_of
  430.  * @see          last_index_of_char
  431.  *)
  432. let last_index_of substr str =
  433.     let last_index = String.length str - 1 in
  434.     if substr = ""
  435.     then last_index
  436.     else let sub_len = String.length substr
  437.          and ch = substr.[0] in
  438.          let rec fn from =
  439.             let i = rindex_from str from ch in
  440.             let found = String.sub str i sub_len in
  441.             if found = substr
  442.             then i
  443.             else fn (i-1) in
  444.     fn last_index
  445.  
  446. (**
  447.  * Replaces all occurances of a character within
  448.  * the string with a different character.
  449.  *
  450.  * @param old character to replace in the string
  451.  * @param nu  character to replace the old character with
  452.  * @param str string in which to replace occurances of a character
  453.  * @return    new string with all occurances of old replaced by nu
  454.  *)
  455. let replace_char old nu str =
  456.     let fn ch = if ch = old
  457.                 then nu
  458.                 else ch in
  459.     String.map fn str
  460.  
  461. (**
  462.  * Splits the string str on sep and returns a list of the resulting strings.
  463.  * The separator string is not included in the returned list of strings.
  464.  * This function is tail-recursive.
  465.  *
  466.  * @param sep separator used to split the string
  467.  * @param str string that (possibly) contains one or more
  468.  *            occurances of the separator
  469.  * @result list of strings that were separated by sep
  470.  *)
  471. let split_on sep str =
  472.     let sep_len = String.length sep in
  473.     let rec fn acc str =
  474.         try let i = last_index_of sep str in
  475.             let pos = sep_len+i
  476.             and len = (String.length str)-sep_len-i in
  477.             let new_str = String.sub str 0 i
  478.             and substr = String.sub str pos len in
  479.             fn (substr::acc) new_str
  480.         with Not_found -> str::acc in
  481.     fn [] str
  482.  
  483. (**
  484.  * Joins the list of strings, interspersing the separator sep between them.
  485.  *
  486.  * @param sep  separator to put between each pair of strings
  487.  * @param strs list of strings to be joined together, with the separator sep
  488.  *             in between each pair
  489.  * @result     string concatenation of the strings in strs, separated by sep
  490.  *)
  491. let join_with sep strs = String.concat sep strs
  492.  
  493.  
  494. (** Returns the string representation of a boolean value. *)
  495. let string_of_boolean flag = match flag with
  496.     | true -> "true"
  497.     | _    -> "false"
  498.  
  499. (** Folds a list into a string. *)
  500. let string_of_list fn lst =
  501.     fold_left fn "" lst |> sprintf "[%s]"
  502.  
  503. (** Returns the string representation of a list of integers. *)
  504. let string_of_int_list lst =
  505.     let fn a n = if a = ""
  506.                  then sprintf "%d" n
  507.                  else sprintf "%s; %d" a n in
  508.     string_of_list fn lst
  509.  
  510. (** Returns the string representation of a list of strings. *)
  511. let string_of_string_list lst =
  512.     let fn a x = if a = ""
  513.                  then sprintf "\"%s\"" x
  514.                  else sprintf "%s; \"%s\"" a x in
  515.     string_of_list fn lst
  516.  
  517.  
  518. (** ----- MISCELLANEOUS FUNCTIONS ----- *)
  519.  
  520. (** Returns the identity of a value. *)
  521. let id x = x
  522.  
  523. (**
  524.  * Extracts the second element of a list,
  525.  * which must have at least two elements.
  526.  *
  527.  * @param lst the list from which to extract the second element
  528.  * @return  second element of list lst
  529.  *)
  530. let second lst = match lst with
  531.     | _::x::xs -> x
  532.     | _        -> failwith "second"
  533.  
  534.  
  535. (* ----- FUNCTION TESTS ----- *)
  536.  
  537. type boolean_test =     { test : string; expect : bool;        result : bool }
  538. type int_test =         { test : string; expect : int;         result : int }
  539. type string_test =      { test : string; expect : string;      result : string }
  540. type int_list_test =    { test : string; expect : int list;    result : int list }
  541. type string_list_test = { test : string; expect : string list; result : string list }
  542.  
  543. type test =
  544.     | BooleanTest    of boolean_test
  545.     | IntTest        of int_test
  546.     | StringTest     of string_test
  547.     | IntListTest    of int_list_test
  548.     | StringListTest of string_list_test
  549.  
  550. (** Prints the result of performing the test. *)
  551. let print_test_result x =
  552.     let print_test test expect result =
  553.         let msg = test ^ " => " ^ result in
  554.         print_endline @@ if expect = result
  555.                          then msg
  556.                          else msg ^ " *** BUT EXPECTED "^ expect in
  557.     match x with
  558.         | BooleanTest x    -> print_test x.test
  559.                                          (string_of_boolean x.expect)
  560.                                          (string_of_boolean x.result)
  561.         | IntTest x        -> print_test x.test
  562.                                          (string_of_int x.expect)
  563.                                          (string_of_int x.result)
  564.         | StringTest x     -> print_test x.test x.expect x.result
  565.         | IntListTest x    -> print_test x.test
  566.                                          (string_of_int_list x.expect)
  567.                                          (string_of_int_list x.result)
  568.         | StringListTest x -> print_test x.test
  569.                                          (string_of_string_list x.expect)
  570.                                          (string_of_string_list x.result)
  571.  
  572. let () =
  573.     let p = ["alpha"; "bravo"; "charlie"; "delta"; "echo"]
  574.     and q = ["foxtrot"; "golf"; "hotel"; "igloo"; "juliet"]
  575.     and r = [1; 2; 3; 4; 5; 6; 7; 8; 9; 10]
  576.     and n = 42 in
  577.     let t = (p, q) in
  578.     let tests = [
  579.         StringListTest { test   = "fst t";
  580.                          expect = ["alpha"; "bravo"; "charlie"; "delta"; "echo"];
  581.                          result = fst t };
  582.         StringListTest { test   = "snd t";
  583.                          expect = ["foxtrot"; "golf"; "hotel"; "igloo"; "juliet"];
  584.                          result = snd t };
  585.         BooleanTest { test = "even n"; expect = true; result = even n };
  586.         BooleanTest { test = "odd n"; expect = false; result = odd n };
  587.         IntTest { test = "signum n"; expect = 1; result = signum n };
  588.         IntTest { test = "negate n"; expect = (-42); result = negate n };
  589.         IntTest { test = "gcd 42 12"; expect = 6; result = gcd 42 12 };
  590.         IntTest { test = "lcm 42 12"; expect = 84; result = lcm 42 12 };
  591.         IntTest { test = "minimum r"; expect = 1; result = minimum r };
  592.         IntTest { test = "maximum r"; expect = 10; result = maximum r };
  593.         IntTest { test = "sum r"; expect = 55; result = sum r };
  594.         IntTest { test = "product r"; expect = 3628800; result = product r };
  595.         BooleanTest { test   = "is_empty \"\"";
  596.                       expect = true;
  597.                       result = is_empty "" };
  598.         BooleanTest { test   = "is_empty \"NOT!\"";
  599.                       expect =false;
  600.                       result = is_empty "NOT!" };
  601.         IntTest { test   = "compare_ignore_case \"JESUS\" \"Jesus\"";
  602.                   expect = 0;
  603.                   result = compare_ignore_case "JESUS" "Jesus" };
  604. (*
  605.         BooleanTest { test   = "begins_with \"H\" \"Hello\"";
  606.                       expect = true;
  607.                       test   = begins_with "H" "Hello" };
  608. *)
  609.         BooleanTest { test   = "ends_with '!' \"Hello!\"";
  610.                       expect = true;
  611.                       result = ends_with "!" "Hello, World!" };
  612.         BooleanTest { test   = "contains_substring \"World\" \"Hello, World!\"";
  613.                       expect = true;
  614.                       result = contains_substring "World" "Hello, World!" };
  615.         BooleanTest { test   = "contains_substring \"world\" \"Hello, World!\"";
  616.                       expect = false;
  617.                       result = contains_substring "world" "Hello, World!" };
  618.         IntTest { test   = "index_of_char '!' \"Hello!, World!\"";
  619.                   expect = 5;
  620.                   result = index_of_char '!' "Hello!, World!" };
  621.         IntTest { test   = "index_of \"World\" \"HelloW, World!\"";
  622.                   expect = 8;
  623.                   result = index_of "World" "HelloW, World!" };
  624.         IntTest { test   = "last_index_of_char '!' \"Hello!, World!\"";
  625.                   expect = 13;
  626.                   result = last_index_of_char '!' "Hello!, World!" };
  627.         IntTest { test   = "last_index_of \"o!\" \"Hello!, World!\"";
  628.                   expect = 4;
  629.                   result = last_index_of "o!" "Hello!, World!" };
  630.         StringTest { test   = "replace_char 'l' 'x' \"Hello, World!\"";
  631.                      expect = "Hexxo, Worxd!";
  632.                      result = replace_char 'l' 'x' "Hello, World!" };
  633.         BooleanTest { test = "null p"; expect = false; result = null p };
  634.         IntTest { test = "length p"; expect = 5; result = length p };
  635.         BooleanTest { test = "elem 3 r"; expect = true; result = elem 3 r };
  636.         StringTest { test = "head q"; expect = "foxtrot"; result = head q };
  637.         StringTest { test = "second q"; expect = "golf"; result = second q };
  638.         StringListTest { test   = "tail q";
  639.                          expect = ["golf"; "hotel"; "igloo"; "juliet"];
  640.                          result = tail q };
  641.         StringListTest { test   = "init p";
  642.                          expect = ["alpha"; "bravo"; "charlie"; "delta"];
  643.                          result = init p };
  644.         StringTest { test = "last p"; expect = "echo"; result = last p };
  645.         IntListTest { test   = "reverse r";
  646.                       expect = [10; 9; 8; 7; 6; 5; 4; 3; 2; 1];
  647.                       result = reverse r };
  648.         StringListTest { test   = "append p q";
  649.                          expect = ["alpha"; "bravo"; "charlie"; "delta"; "echo"; "foxtrot"; "golf"; "hotel"; "igloo"; "juliet"];
  650.                          result = append p q };
  651.         StringListTest { test   = "reverse_append p q";
  652.                          expect = ["echo"; "delta"; "charlie"; "bravo"; "alpha"; "foxtrot"; "golf"; "hotel"; "igloo"; "juliet"];
  653.                          result = reverse_append p q };
  654.         StringListTest { test   = "concat [p; q]";
  655.                          expect = ["alpha"; "bravo"; "charlie"; "delta"; "echo"; "foxtrot"; "golf"; "hotel"; "igloo"; "juliet"];
  656.                          result = concat [p; q] };
  657.         StringListTest { test   = "take 2 p";
  658.                          expect = ["alpha"; "bravo"];
  659.                          result = take 2 p };
  660.         StringListTest { test   = "drop 2 p";
  661.                          expect = ["charlie"; "delta"; "echo"];
  662.                          result = drop 2 p };
  663.         IntTest { test   = "foldl (fun a n -> a-n) 0 r";
  664.                   expect = -55;
  665.                   result = foldl (fun a n -> a-n) 0 r };
  666.         IntTest { test   = "foldr (fun n a -> n+a) r 0";
  667.                   expect = 55;
  668.                   result = foldr (fun n a -> n+a) r 0 };
  669.         IntTest { test   = "foldl' (fun a n -> a-n) r";
  670.                   expect = -53;
  671.                   result = foldl' (fun a n -> a-n) r };
  672.         IntTest { test   = "foldr' (fun a n -> a+n) r";
  673.                   expect = 55;
  674.                   result = foldr' (fun a n -> a+n) r };
  675.         IntListTest { test   = "map String.length p";
  676.                       expect = [5; 5; 7; 5; 4];
  677.                       result = map String.length p };
  678.         StringListTest { test   = "split_on \";\" \"aaa;bbb;;ccc\"";
  679.                          expect = ["aaa"; "bbb"; ""; "ccc"];
  680.                          result = split_on ";" "aaa;bbb;;ccc" };
  681.         StringTest { test   = "join_with \", \" [\"aaa\"; \"bbb\"; \"ccc\"]";
  682.                      expect = "aaa, bbb, ccc";
  683.                      result = join_with ", " ["aaa"; "bbb"; "ccc"] } ] in
  684.     printf "p => %s\n" (string_of_string_list p);
  685.     printf "q => %s\n" (string_of_string_list q);
  686.     printf "r => %s\n" (string_of_int_list r);
  687.     printf "t => (%s, %s)\n" (string_of_string_list p) (string_of_string_list q);
  688.     print_endline "";
  689.     List.iter print_test_result tests;
  690.     print_endline ""
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement