<?xml version="1.0" encoding="UTF-8"?><rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>アンチノミー</title><description>Aren&apos;t learning new things and doing research an antinomy?</description><link>https://rabbitcabbage.github.io/Blogs/</link><item><title>A Learning Note of Bopomofo for Pinyin Users</title><link>https://rabbitcabbage.github.io/Blogs/posts/scribbles-3-zhuyin-fuhao/</link><guid isPermaLink="true">https://rabbitcabbage.github.io/Blogs/posts/scribbles-3-zhuyin-fuhao/</guid><pubDate>Wed, 22 Apr 2026 00:00:00 GMT</pubDate><content:encoded>&lt;blockquote&gt;
&lt;p&gt;Author: Qijia Fan&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;本文是为了帮助习惯使用汉语拼音的读者学习注音符号而写的学习笔记，希望能让读者更好地了解汉字标音系统的发展历史与发音逻辑。&lt;/p&gt;
&lt;h2&gt;背景&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;注音符号&lt;/strong&gt;（Bopomofo）是由清末民初的语言学家设计的一套用于标注汉字读音的符号系统，于 1918 年由当时教育部正式颁布。其英文名称「Bopomofo」取自前四个符号的读音：ㄅ（b）、ㄆ（p）、ㄇ（m）、ㄈ（f）。目前的使用情况大致如下：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;在中国大陆，注音符号自 1958 年起逐步由汉语拼音取代，但在字典等工具书中仍有标注。以个人观察而言，大陆部分建国前后出生的长辈仍能辨识并使用注音符号，年轻一代则对此较为陌生。&lt;/li&gt;
&lt;li&gt;在台湾地区，注音符号至今仍广泛应用于学校教育与日常生活。&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;注音符号表与拼读&lt;/h2&gt;
&lt;p&gt;注音符号表由声母、介母、韵母和声调符号组成，其中介母与韵母在汉语拼音中合称为韵母。接下来我们分别给出注音符号表与汉语拼音的对应关系，并说明一些拼读规则。&lt;/p&gt;
&lt;h3&gt;声母&lt;/h3&gt;
&lt;p&gt;接下来的两个表格依照注音符号在注音键盘上的排列顺序排列，共 6 + 5 列（栏），每一列（栏）的表头表示该列（栏）的第一个符号在注音键盘上的位置（参见下一节）。&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;code&gt;1&lt;/code&gt;&lt;/th&gt;
&lt;th&gt;&lt;code&gt;2&lt;/code&gt;&lt;/th&gt;
&lt;th&gt;&lt;code&gt;3&lt;/code&gt;&lt;/th&gt;
&lt;th&gt;&lt;code&gt;4&lt;/code&gt;&lt;/th&gt;
&lt;th&gt;&lt;code&gt;5&lt;/code&gt;&lt;/th&gt;
&lt;th&gt;&lt;code&gt;6&lt;/code&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;ㄅ&lt;/strong&gt; b&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;ㄉ&lt;/strong&gt; d&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;ㄓ&lt;/strong&gt; zh(i)&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;ㄆ&lt;/strong&gt; p&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;ㄊ&lt;/strong&gt; t&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;ㄍ&lt;/strong&gt; g&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;ㄐ&lt;/strong&gt; j&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;ㄔ&lt;/strong&gt; ch(i)&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;ㄗ&lt;/strong&gt; z(i)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;ㄇ&lt;/strong&gt; m&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;ㄋ&lt;/strong&gt; n&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;ㄎ&lt;/strong&gt; k&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;ㄑ&lt;/strong&gt; q&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;ㄕ&lt;/strong&gt; sh(i)&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;ㄘ&lt;/strong&gt; c(i)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;ㄈ&lt;/strong&gt; f&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;ㄌ&lt;/strong&gt; l&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;ㄏ&lt;/strong&gt; h&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;ㄒ&lt;/strong&gt; x&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;ㄖ&lt;/strong&gt; r(i)&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;ㄙ&lt;/strong&gt; s(i)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3&gt;介母与韵母&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;code&gt;7&lt;/code&gt;&lt;/th&gt;
&lt;th&gt;&lt;code&gt;8&lt;/code&gt;&lt;/th&gt;
&lt;th&gt;&lt;code&gt;9&lt;/code&gt;&lt;/th&gt;
&lt;th&gt;&lt;code&gt;0&lt;/code&gt;&lt;/th&gt;
&lt;th&gt;&lt;code&gt;-&lt;/code&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;ㄚ&lt;/strong&gt; a&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;ㄞ&lt;/strong&gt; ai&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;ㄢ&lt;/strong&gt; an&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;ㄦ&lt;/strong&gt; er&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;ㄧ&lt;/strong&gt; y/i&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;ㄛ&lt;/strong&gt; o&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;ㄟ&lt;/strong&gt; ei&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;ㄣ&lt;/strong&gt; en&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;ㄨ&lt;/strong&gt; w/u&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;ㄜ&lt;/strong&gt; e&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;ㄠ&lt;/strong&gt; ao&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;ㄤ&lt;/strong&gt; ang&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;ㄩ&lt;/strong&gt; yu/ü&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;ㄝ&lt;/strong&gt; ê&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;ㄡ&lt;/strong&gt; ou&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;ㄥ&lt;/strong&gt; eng&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;在上表中，7 列为介母，其余的列为韵母。&lt;/p&gt;
&lt;p&gt;读者可能会注意到，部分汉语拼音中的韵母（如 in(g), ong 等）并未在上表中出现，而这些韵母在注音符号中是由介母与韵母组合而成的，具体见之后的拼读规则说明第 3 条。&lt;/p&gt;
&lt;h3&gt;声调&lt;/h3&gt;
&lt;p&gt;注音符号的声调标注与汉语拼音略有不同。在汉语拼音中，阴平、阳平、上声、去声分别用 「ˉ」「ˊ」「ˇ」「ˋ」四个符号标注，未标注声调符号表轻声；而在注音符号中，阳平、上声、去声仍用「ˊ」「ˇ」「ˋ」符号标注，但阴平通常不标注声调符号「ˉ」，而轻声需用「˙」符号标注：&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;标音系统&lt;/th&gt;
&lt;th&gt;阴平&lt;/th&gt;
&lt;th&gt;阳平&lt;/th&gt;
&lt;th&gt;上声&lt;/th&gt;
&lt;th&gt;去声&lt;/th&gt;
&lt;th&gt;轻声&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;汉语拼音&lt;/td&gt;
&lt;td&gt;ā&lt;/td&gt;
&lt;td&gt;á&lt;/td&gt;
&lt;td&gt;ǎ&lt;/td&gt;
&lt;td&gt;à&lt;/td&gt;
&lt;td&gt;a&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;注音符号&lt;/td&gt;
&lt;td&gt;ㄚˉ/ㄚ&lt;/td&gt;
&lt;td&gt;ㄚˊ&lt;/td&gt;
&lt;td&gt;ㄚˇ&lt;/td&gt;
&lt;td&gt;ㄚˋ&lt;/td&gt;
&lt;td&gt;ㄚ˙&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3&gt;拼读规则说明&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;该系统区分两种 i：[i] 与 [ɨ]（例如 si），后者直接用声母（不应在后加「ㄧ」）。
&lt;blockquote&gt;
&lt;p&gt;例：「智」的注音为「ㄓˋ」而非「ㄓㄧˋ」。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;/li&gt;
&lt;li&gt;ㄝ（ê）是 /ɛ/，如「欸」「诶」等，也是 -ei, -ie/ye, -üe/yue 中 e 的实际发音，故 -ie/ye, -üe/yue 的注音分别为「ㄧㄝ」「ㄩㄝ」。
&lt;blockquote&gt;
&lt;p&gt;例：「谢」的注音为「ㄒㄧㄝˋ」而非「ㄒㄧㄜˋ」。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;/li&gt;
&lt;li&gt;-ian/yan, -üan/yuan 的注音还是「ㄧㄢ」「ㄩㄢ」，可以理解为汉语拼音与注音符号系统均不区分 an 与 &quot;ên&quot;。&lt;/li&gt;
&lt;li&gt;-in/yin, -ing/ying, -ong, -iong/yong 应分别理解为 -ien（ㄧㄣ）, -ieng（ㄧㄥ）, -ueng（ㄨㄥ）, -üeng（ㄩㄥ）。
&lt;blockquote&gt;
&lt;p&gt;例：「红」的拼音和注音分别为「hóng」「ㄏㄨㄥˊ」；「穷」的拼音和注音分别为「qióng」「ㄑㄩㄥˊ」。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;/li&gt;
&lt;li&gt;iu, ui, un (ün) 分别是 iou, uei, uen (üen) 的缩略形式。&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;注音输入法&lt;/h2&gt;
&lt;p&gt;注音输入法的键位排列与注音符号表的排列顺序高度一致，见下图：&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;../../assets/zhuyin_keyboard.png&quot; alt=&quot;注音输入法键位图&quot; /&gt;&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- &lt;img src=&quot;../picture/zhuyin_keyboard.png&quot; alt=&quot;注音输入法键位图&quot; /&gt; --&amp;gt;&lt;/p&gt;
&lt;p&gt;其中，&lt;code&gt;3&lt;/code&gt;、&lt;code&gt;4&lt;/code&gt;、&lt;code&gt;6&lt;/code&gt;、&lt;code&gt;7&lt;/code&gt; 四个键位呼应了上一节注音符号表中的预留空格，用于输入声调，阴平则用 Space 键输入（对应不标注声调符号）。&lt;/p&gt;
&lt;p&gt;TODO&lt;/p&gt;
</content:encoded><author>Qijia Fan</author></item><item><title>Scribbles-2 OCaml Types</title><link>https://rabbitcabbage.github.io/Blogs/posts/scribbles-2-basics-of-ocaml/</link><guid isPermaLink="true">https://rabbitcabbage.github.io/Blogs/posts/scribbles-2-basics-of-ocaml/</guid><pubDate>Tue, 24 Feb 2026 00:00:00 GMT</pubDate><content:encoded>&lt;h2&gt;Notes on pattern matching&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://ocaml.org/manual/5.4/patterns.html&quot;&gt;Patterns that everyone likes&lt;/a&gt;.
The &lt;code&gt;let&lt;/code&gt; expression is actually doing a pattern matching. Consider the dynamic semantics of &lt;code&gt;let p = e1 in e2&lt;/code&gt;. We first evaluate &lt;code&gt;e1&lt;/code&gt; to a value &lt;code&gt;v1&lt;/code&gt;. The &lt;code&gt;p&lt;/code&gt; can be any pattern, and we match &lt;code&gt;v1&lt;/code&gt; with pattern &lt;code&gt;p&lt;/code&gt;. If they doesn&apos;t match, there will be a &lt;code&gt;Match_failure&lt;/code&gt;, otherwise it matches and generates bindings (emmm perhaps no bindings are produced because I can write super weird &lt;code&gt;let&lt;/code&gt; in the following). These bindings will be used for substitutions in &lt;code&gt;e2&lt;/code&gt;, generating another &lt;code&gt;e2&apos;&lt;/code&gt; and evluates to &lt;code&gt;v2&lt;/code&gt;.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;let 5 = 5 in 6;;

(* Line 1, characters 4-5:
Warning 8 [partial-match]: this pattern-matching is not exhaustive.
Here is an example of a case that is not matched:
0

- : int = 6 *)

let 5 = 8 in 6;;

(* Line 1, characters 4-5:
Warning 8 [partial-match]: this pattern-matching is not exhaustive.
Here is an example of a case that is not matched:
0

Exception: Match_failure (&quot;//toplevel//&quot;, 1, 4). *)
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;Types of OCaml&lt;/h2&gt;
&lt;h3&gt;Variants&lt;/h3&gt;
&lt;p&gt;Variants are like enums in C. Variants are &lt;strong&gt;data types&lt;/strong&gt;, and the value of expressions in this type is exactly one of the defined values.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;type day = Sun | Mon | Tue | Wed | Thu | Fri | Sat
let d = Tue
let int_of_day d =
  match d with
  | Sun -&amp;gt; 1
  | Mon -&amp;gt; 2
  | Tue -&amp;gt; 3
  | Wed -&amp;gt; 4
  | Thu -&amp;gt; 5
  | Fri -&amp;gt; 6
  | Sat -&amp;gt; 7
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The definition of variants is also shadowing in different scopes.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;type t1 = C | D
type t2 = D | E
let x = D
(* val x : t2 = D *)
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Records&lt;/h3&gt;
&lt;p&gt;A record is a composite of other types of data, and forming a new type. The pattern matching &lt;code&gt;{day; food; amount}&lt;/code&gt; is sugar for &lt;code&gt;{day = date; food = menu; amount = int}&lt;/code&gt;.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;type date = Mon | Tue | Wed| Thu;;
(* type date = Mon | Tue | Wed | Thu *)
type menu = Chicken | Beef | Fish;;
(* type menu = Chicken | Beef | Fish *)
type plan = { day : date; food: menu; amount: int};;
(* type plan = { day : date; food : menu; amount : int; } *)
{day = Mon; food = Beef; amount = 10};;
(* - : plan = {day = Mon; food = Beef; amount = 10} *)
let p = {day = Tue; food = Fish; amount = 1};;
(* val p : plan = {day = Tue; food = Fish; amount = 1} *)
p.food;;
(* - : menu = Fish *)
match p with {day; food; amount} -&amp;gt; amount;;
(* - : int = 1 *)
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Tuples&lt;/h3&gt;
&lt;p&gt;Tuples are a composite of other types of data. But the components are not named, they are identified by position. We can also explicitly write a tuple&apos;s type using the syntax &lt;code&gt;*&lt;/code&gt; (which is actually doing &lt;strong&gt;type synonyms&lt;/strong&gt; of already existing types).&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;(1,&quot;hello&quot;,true);;
(* - : int * string * bool = (1, &quot;hello&quot;, true) *)
match (1,&quot;hello&quot;,true) with (x,y,z) -&amp;gt; (string_of_int x) ^ y ^ (string_of_bool z);;
(* - : string = &quot;1hellotrue&quot; *)
type tup = int * int * bool;;
(* type tup = int * int * bool *)
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Tagged union&lt;/h3&gt;
&lt;p&gt;We can take a union of two types and give it one name, or view one type as a union with two tags. Inside this union, the new tags we design can tell us which subset a value comes from.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;type string_or_int =
  | Str of string
  | Int of int

type colored_int =
  | Blue of int
  | Pink of int
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Then we can discriminate the tagged values even they are the same original type.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;let increment_pink = function
  | Blue i -&amp;gt; i
  | Pink i -&amp;gt; i + 1
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The syntax is like below, &lt;code&gt;[]&lt;/code&gt; means optional.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;type t = C1 [of t1] | ... | Cn [of tn]
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;If a &lt;code&gt;Ci&lt;/code&gt; is constant, i.e. a tag without different values, then you can write an expression just with &lt;code&gt;Ci&lt;/code&gt;; else if it&apos;s non-constant, like &lt;code&gt;Ci of string&lt;/code&gt;, then we should write an expression as &lt;code&gt;Ci e&lt;/code&gt;, e.g. &lt;code&gt;Ci &quot;hello&quot;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;The dynamic semantics have one subtle thing: If &lt;code&gt;t = ... | C of t&apos; | ...&lt;/code&gt;, then any expression of type &lt;code&gt;t&apos;&lt;/code&gt; also has the variant type &lt;code&gt;t&lt;/code&gt;, can be viewed as a &lt;code&gt;C e&lt;/code&gt; expression, i.e. if &lt;code&gt;e : t&apos;&lt;/code&gt; then &lt;code&gt;C e : t&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;And in the pattern matching, the non-constant expression is matched by &lt;code&gt;C p&lt;/code&gt;. Examples can be find in next section (&lt;code&gt;area&lt;/code&gt; and &lt;code&gt;center&lt;/code&gt;).&lt;/p&gt;
&lt;h3&gt;Algebraic data type&lt;/h3&gt;
&lt;p&gt;Variants are one-of types, also called &amp;lt;font color=&quot;#c0504d&quot;&amp;gt;sum types&amp;lt;/font&amp;gt;. Records and tuples are each-of types (Cartesian products). also called &amp;lt;font color=&quot;#c0504d&quot;&amp;gt;product types&amp;lt;/font&amp;gt;. Algebraic data types contain both sum types and product types, e.g. the typical example, we first define a pair (each of, product type), then define a tagged union with three tags (one of, sum type), and in some tags, we use the tuple (or pair) again (product type).&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;type point = float * float
type shape =
  | Point of point
  | Circle of point * float (* center and radius *)
  | Rect of point * point (* lower-left and upper-right corners *)

let area = function
  | Point _ -&amp;gt; 0.0
  | Circle (_, r) -&amp;gt; Float.pi *. (r ** 2.0)
  | Rect ((x1, y1), (x2, y2)) -&amp;gt;
      let w = x2 -. x1 in
      let h = y2 -. y1 in
      w *. h

let center = function
  | Point p -&amp;gt; p
  | Circle (p, _) -&amp;gt; p
  | Rect ((x1, y1), (x2, y2)) -&amp;gt; ((x2 +. x1) /. 2.0, (y2 +. y1) /. 2.0)
&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote&gt;
&lt;p&gt;In the algebraic data type, &quot;one-of&quot; means the a value of a variant is formed by &lt;em&gt;one of&lt;/em&gt; the constructors, while &quot;each-of&quot; means the constructors can have tuples or records, whose value have a sub-value from &lt;em&gt;each of&lt;/em&gt; their component types.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The variant type is a collection of constructors. The constructor here serves as both a formation of a value a tag (like a sub-type in this variant type). Variant types are also called tagged unions.&lt;/p&gt;
&lt;p&gt;Variant types can be defined recursively by mentioning their own name inside constructors.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;type intlist = Nil | Cons of int * intlist
let lst3  = Cons (3, Nil) (* a pair of type int * list *)
let lst123 = Cons (1, Cons (2, Cons (3, Nil)))
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Types may be mutually recursive if you use the &lt;code&gt;and&lt;/code&gt; keyword:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;type node = {value : int; next : mylist}
and mylist = Nil | Node of node
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;But such mutual recursion must have at least one type that can end, otherwise it will be cyclic and cause an error.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;type t = u and u = t
(* File &quot;[12]&quot;, line 1, characters 0-10:
1 | type t = u and u = t
    ^^^^^^^^^^
Error: The type abbreviation t is cyclic:
         t = u,
         u = t *)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Record type can also be recursive. The textbook give such an example:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;type node = {value : int; next : node}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;But this type is not useful. The only values we can create from this type must refer back to itself in a loop because this recursion doesn&apos;t end.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;let rec n = {value = 1; {value = 2; {value = 3; n}}}
&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote&gt;
&lt;p&gt;Remark from 1024th: coinductive&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Variant type can have type parameters.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;type &apos;a mylist = Nil | Cons of &apos;a * &apos;a mylist
let lst3 = Cons (3, Nil)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;If we write functions for such parameterized types, we may want to ensure that the &lt;code&gt;&apos;a&lt;/code&gt; type annotation can be omitted safely, that is we don&apos;t use operations that are specific to some types, like &lt;code&gt;int&lt;/code&gt; or &lt;code&gt;string&lt;/code&gt;.&amp;lt;font color=&quot;#c0504d&quot;&amp;gt; (polymorphism)&amp;lt;/font&amp;gt; Otherwise, we will give up polymorphism by restricting what &lt;code&gt;&apos;a&lt;/code&gt; can be.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;(directly from book) There’s another kind of variant in OCaml that supports this kind of programming: &lt;em&gt;polymorphic variants&lt;/em&gt;. Polymorphic variants are just like variants, except:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;You don’t have to declare their &lt;code&gt;type&lt;/code&gt; or constructors before using them.&lt;/li&gt;
&lt;li&gt;There is no name for a polymorphic variant type. (So another name for this feature could have been “&amp;lt;font color=&quot;#4bacc6&quot;&amp;gt;anonymous variants&amp;lt;/font&amp;gt;”.)&lt;/li&gt;
&lt;li&gt;The constructors of a polymorphic variant &amp;lt;font color=&quot;#4bacc6&quot;&amp;gt;start with a backquote character&amp;lt;/font&amp;gt;.
Using polymorphic variants, we can rewrite &lt;code&gt;f&lt;/code&gt;:&lt;/li&gt;
&lt;/ol&gt;
&lt;/blockquote&gt;
&lt;pre&gt;&lt;code&gt;let f = function
  | 0 -&amp;gt; `Infinity
  | 1 -&amp;gt; `Finite 1
  | n -&amp;gt; `Finite (-n)
(* val f : int -&amp;gt; [&amp;gt; `Finite of int | `Infinity ] = &amp;lt;fun&amp;gt; *)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And &lt;code&gt;f&lt;/code&gt; returns a value of type &lt;code&gt;&apos;Finite&lt;/code&gt; or &lt;code&gt;&apos;Infinity&lt;/code&gt;. The backquote is still there.&lt;/p&gt;
&lt;h3&gt;Option&lt;/h3&gt;
&lt;p&gt;An option is actually a one-of type, it can be either having an element (e.g. an option &lt;code&gt;Some 22&lt;/code&gt;, which has type &lt;code&gt;int option&lt;/code&gt;) or being empty (an option &lt;code&gt;None&lt;/code&gt;, which has type &lt;code&gt;&apos;a option&lt;/code&gt;). But &lt;code&gt;option&lt;/code&gt; itself is not a type, it produce a new type &lt;code&gt;t option&lt;/code&gt; from any type &lt;code&gt;t&lt;/code&gt;.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;let rec list_max = function
  | [] -&amp;gt; None
  | h :: t -&amp;gt; begin
      match list_max t with
        | None -&amp;gt; Some h
        | Some m -&amp;gt; Some (max h m)
      end
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The type will be &lt;code&gt;val list_max : &apos;a list -&amp;gt; &apos;a option = &amp;lt;fun&amp;gt;&lt;/code&gt;.
And the &lt;code&gt;begin&lt;/code&gt; and &lt;code&gt;end&lt;/code&gt; is equivalent to &lt;code&gt;()&lt;/code&gt; in functionality.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;OCaml options force the programmer to include a branch in the pattern match for &lt;code&gt;None&lt;/code&gt;, thus guaranteeing that the programmer thinks about the right thing to do when there’s nothing there. So we can think of options as a principled way of eliminating &lt;code&gt;null&lt;/code&gt; from the language.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;None&lt;/code&gt; is a value of type &lt;code&gt;&apos;a option&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Some e&lt;/code&gt; is an expression of type &lt;code&gt;t option&lt;/code&gt; if &lt;code&gt;e : t&lt;/code&gt;. If &lt;code&gt;e ==&amp;gt; v&lt;/code&gt; then &lt;code&gt;Some e ==&amp;gt; Some v&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;
&lt;h3&gt;Association lists&lt;/h3&gt;
&lt;p&gt;Map maps keys to values. In OCaml it can be trivially implemented in association list, which is a list of pairs with constant insertion time and linear lookup time.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;let mymap : (string * int) list =
  [(&quot;Level 1&quot;, 128); (&quot;Level 2&quot;, 192); (&quot;Level 3&quot;, 256)];;
let insert k v lst = (k, v) :: lst;;
let rec lookup k = function
  | [] -&amp;gt; None
  | (k&apos;, v) :: t -&amp;gt; if k = k&apos; then Some v else lookup k t;;
lookup &quot;Level 1&quot; mymap;;
(* - : int option = Some 128 *)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The standard library implements association lists with &lt;a href=&quot;https://ocaml.org/manual/5.4/api/List.html&quot;&gt;List&lt;/a&gt; module. Module names in OCaml use &lt;code&gt;CamelCase&lt;/code&gt;, and function names use &lt;code&gt;snake_case&lt;/code&gt;.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;val fold_left : (&apos;acc -&amp;gt; &apos;a -&amp;gt; &apos;acc) -&amp;gt; &apos;acc -&amp;gt; &apos;a list -&amp;gt; &apos;acc
val fold_right : (&apos;a -&amp;gt; &apos;acc -&amp;gt; &apos;acc) -&amp;gt; &apos;a list -&amp;gt; &apos;acc -&amp;gt; &apos;acc
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The &lt;code&gt;fold_left&lt;/code&gt; is of type &lt;code&gt;List.fold_left : (&apos;b -&amp;gt; &apos;a -&amp;gt; &apos;b) -&amp;gt; &apos;b -&amp;gt; &apos;a list -&amp;gt; &apos;b&lt;/code&gt;.
so it takes three arguments &lt;code&gt;fold_left f init list&lt;/code&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;the first argument &lt;code&gt;f&lt;/code&gt;: is a function, like the operator &lt;code&gt;+&lt;/code&gt;, or the Cons. It takes the current accumulator of type &lt;code&gt;&apos;b&lt;/code&gt;, takes one element of type &lt;code&gt;&apos;a&lt;/code&gt;, do the operation to get a new accumulated value of type &lt;code&gt;&apos;b&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;the second argument is the initial accumulator&lt;/li&gt;
&lt;li&gt;the third argument is a list, we want to do the operation &lt;code&gt;f&lt;/code&gt; from the left side of the list.
&lt;code&gt;fold_left&lt;/code&gt; is tail-recursive while the &lt;code&gt;fold_right&lt;/code&gt; is not, because the head can be popped out from left side in $O(1)$ time.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Quality of life in OCaml&lt;/h2&gt;
&lt;h3&gt;OUnit&lt;/h3&gt;
&lt;p&gt;Unit tests framework for OCaml: &lt;a href=&quot;https://gildor478.github.io/ounit/ounit2/index.html&quot;&gt;OUnit&lt;/a&gt;
Configure the dune project with &lt;code&gt;dune&lt;/code&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;(executable
 (name test)
 (libraries ounit2))
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Write a random &lt;code&gt;mycode.ml&lt;/code&gt; file for invoking.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;let ask_ds x = match x with
  | &quot;good ds&quot; -&amp;gt; &quot;Thanks&quot;
  | &quot;sleepy ds&quot; -&amp;gt; &quot;OK&quot;
  | &quot;bad ds&quot; -&amp;gt; &quot;No&quot;
  | _ -&amp;gt; failwith &quot;Not in Dictionary&quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Use the code an run a unit test. Each test case has a string giving it a descriptive name, and a function to run as the test case. In between is a custom operator &lt;code&gt;&amp;gt;::&lt;/code&gt;. &lt;code&gt;&amp;gt;:::&lt;/code&gt; is in between of the name of this test suite and the test cases.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;open OUnit2
open Mycode

let tests = &quot;test suit for asking ds&quot; &amp;gt;::: [
  &quot;say thanks&quot; &amp;gt;:: (fun _ -&amp;gt; assert_equal &quot;Thanks&quot; (ask_ds &quot;good ds&quot;));
  &quot;say no&quot; &amp;gt;:: (fun _ -&amp;gt; assert_equal &quot;No&quot; (ask_ds &quot;bad ds&quot;));
  &quot;say zzz&quot; &amp;gt;:: (fun _ -&amp;gt; assert_equal &quot;ZZZ&quot; (ask_ds &quot;sleepy ds&quot;) ~printer:(fun x -&amp;gt; x)); (* ~printer is an argument. Get `expected: ZZZ but got: OK` *)
  &quot;say bye&quot; &amp;gt;:: (fun _ -&amp;gt; assert_equal &quot;Bye&quot; (ask_ds &quot;bye ds&quot;))
]

let _ = run_test_tt_main tests
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The output will be like&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;Error: test suit for asking ds:3:say bye.
Failure(&quot;Not in Dictionary&quot;)

Error: test suit for asking ds:2:say zzz.
expected: ZZZ but got: OK

&lt;/code&gt;&lt;/pre&gt;
</content:encoded><author>Shen, 1024th</author></item><item><title>Scribbles-1 Basics of OCaml</title><link>https://rabbitcabbage.github.io/Blogs/posts/scribbles-1-basics-of-ocaml/</link><guid isPermaLink="true">https://rabbitcabbage.github.io/Blogs/posts/scribbles-1-basics-of-ocaml/</guid><pubDate>Sat, 31 Jan 2026 00:00:00 GMT</pubDate><content:encoded>&lt;h2&gt;The properties of OCaml&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/First-class_citizen&quot;&gt;First-Class Citizens&lt;/a&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;OCaml is a &lt;em&gt;statically-typed&lt;/em&gt; and &lt;em&gt;type-safe&lt;/em&gt; programming language.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;A statically-typed language detects type errors at compile time; if a type error is detected, the language won’t allow execution of the program.&lt;/li&gt;
&lt;li&gt;A type-safe language limits which kinds of operations can be performed on which kinds of data.
Python is type-safe but &lt;em&gt;dynamically typed&lt;/em&gt;. That is, type errors are caught only at run time. C and C++, are statically typed but not type safe: they check for some type errors, but don’t guarantee the absence of all type errors. That is, there’s no guarantee that a type error won’t occur at run time.&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;
&lt;p&gt;C++ is not totally type safe. &lt;code&gt;malloc/free&lt;/code&gt; will return pointer of &lt;code&gt;void *&lt;/code&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;int x = 10;
char* p = reinterpret_cast&amp;lt;char*&amp;gt;(&amp;amp;x);
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;Algebraic data types&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;[[Type inference]]&lt;/strong&gt;: we have to ensure the program is correctly written for the compiler to do type inference. You can annotate types but cannot cast them.
&lt;code&gt;(5 : int)&lt;/code&gt; &lt;code&gt;(5. : int)&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Parametric polymorphism: functions and data structures can be parameterized over types, functioning like the &lt;code&gt;template&amp;lt;typename T&amp;gt;&lt;/code&gt; in C++. But C++ templates are (mostly) instantiated and type-checked &lt;strong&gt;per use&lt;/strong&gt;, while OCaml’s polymorphic functions are type-checked &lt;strong&gt;once at definition&lt;/strong&gt;. In C++, a template definition can be accepted even if some operations inside it would be ill-formed for certain &lt;code&gt;T&lt;/code&gt;; errors typically appear only when C++ makes an instantiation with a specific type substitution and it is incompatible with the template, so the runtime is good while compilation is slow. OCaml compilation directly does type-checking at the definition, to ensure the template to be a general, abstract type (it must holds for every type, so type-specific operations like &lt;code&gt;+1&lt;/code&gt; fails right away), then does the substitution at run time. So OCaml is &lt;strong&gt;value agnostic&lt;/strong&gt;. &amp;lt;font color=&quot;#4bacc6&quot;&amp;gt;The check is supported by Hindley–Milner style type inference/unification.&amp;lt;/font&amp;gt;&lt;/li&gt;
&lt;li&gt;Garbage collection&lt;/li&gt;
&lt;li&gt;Modules&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;OCaml Basics&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Syntax&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Semantics&lt;/strong&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;type-checking rules&lt;/strong&gt; (static semantics): produce a type or fail with an error&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;evaluation rules&lt;/strong&gt; (dynamic semantics)
OCaml does type-checking at compile time like Java and C++, while Python at runtime.&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Compile a file, run and clear&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;ocamlc - o hello.byte hello.ml
./hello.byte
rm hello.byte hello.cmi hello.cmo
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Or use dune at ease
&lt;code&gt;dune&lt;/code&gt;: &lt;code&gt;(executable (name hello))&lt;/code&gt;
&lt;code&gt;dune-project&lt;/code&gt;: &lt;code&gt;(lang dune 3.21)&lt;/code&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;dune build hello.exe
_build/default/hello.exe
dune exec ./hello.exe
dune clean
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;dune init project auto_hello
cd auto_hello
dune exec bin/main.exe
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;OCaml&apos;s toplevel is called &lt;em&gt;utop&lt;/em&gt; as a &lt;strong&gt;calculator+command-line interface&lt;/strong&gt; (utop is so luxury, even with tab completion and syntax highlighting), some other languages call the toplevel a REPL. Like JShell for Java and interactive interpreter for Python. It&apos;s working logic is Read-Eval-Print Loop.
Typically when we write OCaml in a &lt;code&gt;.ml&lt;/code&gt; file we don&apos;t need &lt;code&gt;;;&lt;/code&gt;. It&apos;s only needed when we write in a interactive session like utop. The toplevel reads until hitting one &lt;code&gt;;;&lt;/code&gt; to know that OK this is one chunk of input (&lt;em&gt;&lt;strong&gt;a toplevel phrase&lt;/strong&gt;&lt;/em&gt;). So &lt;code&gt;;;&lt;/code&gt; means where phrase is complete and ready for parsing and evaluation.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;#quit;; (* quitting utop. start with another &quot;#&quot; *)
42;;
(* - : int = 42 *)
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Expression&lt;/h3&gt;
&lt;p&gt;OCaml integers are represented as 63 bits, using one bit in the 64-bit word as a mark of integer (distinguishing from pointer, which is for garbage collection) (previously it&apos;s 31 bits).
OCaml floats are float64. Syntactically, they must always contain a dot and the addition, division and multiplication of floats must also has a dot &lt;code&gt;+.&lt;/code&gt; &lt;code&gt;/.&lt;/code&gt; &lt;code&gt;*.&lt;/code&gt; .
Char takes 1 byte. String is sequence of chars. OCaml values don&apos;t have methods like C++ to convert themselves to strings, but we can use &lt;code&gt;string_of_xxx&lt;/code&gt;.
operator &lt;code&gt;lsr&lt;/code&gt; is logical shift right, while &lt;code&gt;asr&lt;/code&gt; is arithmetic shif right. &lt;code&gt;asr&lt;/code&gt; fills the left with sign bit while &lt;code&gt;lsr&lt;/code&gt; fills with 0s.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;3.14 *. (float_of_int 2);;
(* - : float = 6.28 *)
(int_of_float 3.14) * 2;;
(* - : int = 6 *)
char_of_int(5);;
(* - : char = &apos;\005&apos; *)
int_of_char(&apos;t&apos;);;
(* - : int = 116 *)
string_of_float(3.33);;
(* - : string = &quot;3.33&quot; *)
&quot;abcd&quot;.[0];;
(* - : char = &apos;a&apos; *)
-40 lsr 2;;
(* - : int = 2305843009213693942 *)
-40 asr 2;;
(* - : int = -10 *)
2305843009213693942 lsl 2;;
(* - : int = -40 *)
&quot;str&quot; ^ &quot;ing&quot;;;
(* - : string = &quot;string&quot; *)
[2,3];;
(* - : (int * int) list = [(2, 3)] *) (* list of pairs *)
[1,2] @ [3,4];;
(* - : (int * int) list = [(1, 2); (3, 4)] *)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;OCaml also has references. They are expressions but they simulates the behavior of variables (&amp;lt;font color=&quot;#f79646&quot;&amp;gt;Everything is an expression&amp;lt;/font&amp;gt; in OCaml). &lt;code&gt;ref 0&lt;/code&gt; is an expression, it evaluates to return a value with type &lt;code&gt;int ref&lt;/code&gt;. &lt;code&gt;!r&lt;/code&gt; is also an expression, it evalutes to the content referred. &lt;code&gt;r:=5&lt;/code&gt; is assigning value to the reference, and it&apos;s also an expression, it evaluates to a value &lt;code&gt;()&lt;/code&gt; with type &lt;code&gt;unit&lt;/code&gt;.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;let r = ref 0;;
(* val r : int ref = {contents = 0} *)
!r;;
(* - : int = 0 *)
r := 1;;
(* - : unit = () *)
let x = if (r:=5; !r &amp;gt; 0) then &quot;hello&quot; else &quot;bye&quot;;;
(* val x : string = &quot;hello&quot; *)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Structural Equality &lt;code&gt;=&lt;/code&gt; (inequality &lt;code&gt;&amp;lt;&amp;gt;&lt;/code&gt;) is for value comparison, which ignores the memory address, like &lt;code&gt;==&lt;/code&gt; in python, while physical equality &lt;code&gt;==&lt;/code&gt; (inequality &lt;code&gt;!=&lt;/code&gt;) compaires memory address, like &lt;code&gt;==&lt;/code&gt; between pointers in C/C++.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;let r1 = ref 42;;
(* val r1 : int ref = {contents = 42} *)
let r2 = ref 42;;
(* val r2 : int ref = {contents = 42} *)
r1 = r2;;
(* - : bool = true *)
!r1 = !r2;;
(* - : bool = true *)
r1 == r2;;
(* - : bool = false *)
!r1 == !r2;;
(* - : bool = true *)
let r3 = r1;;
(* val r3 : int ref = {contents = 42} *)
r3 == r1;;
(* - : bool = true *)
r3 &amp;lt;&amp;gt; r2;;
(* - : bool = false *)
r3 != r2;;
(* - : bool = true *)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;With regard to why &lt;code&gt;!r1 == !r2&lt;/code&gt; is true, OCaml implements a &quot;small integer optimization&quot; ==using &lt;strong&gt;tagged pointers&lt;/strong&gt; to store immediate integer values directly in a single machine word without requiring extra memory allocation (boxing)==.
If we use this experiment to heap objects, like floats or lists, it will be &lt;code&gt;false&lt;/code&gt; because their addresses are different.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;let x = ref 3.14;;
(* val x : float ref = {contents = 3.14} *)
let y = ref 3.14;;
(* val y : float ref = {contents = 3.14} *)
!x == !y;;
(* - : bool = false *)
!x != !y;;
(* - : bool = true *)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;It seems that even large integers also has &lt;code&gt;==&lt;/code&gt; to be true. That&apos;s amasing.&lt;/p&gt;
&lt;p&gt;If assertion is true, OCaml returns a value of type unit&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;assert (1 == 1);;
(* - : unit = () *)
assert (1 == 2);;
(* Exception:
Assert_failure (&quot;//toplevel//&quot;, 1, 0). *)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;When there is no &lt;code&gt;else&lt;/code&gt; the default empty expression is &lt;code&gt;()&lt;/code&gt;, so the type-checking fails if there is no &lt;code&gt;else&lt;/code&gt; and the &lt;code&gt;then&lt;/code&gt; branch&apos;es type is not unit.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;if 3 + 5 &amp;gt; 2 then &quot;yay!&quot; else &quot;boo!&quot;;;
(* - : string = &quot;yay!&quot; *)
if &apos;a&apos; &amp;gt; &apos;b&apos; then ();;
(* - : unit = () *)
if &apos;a&apos; &amp;gt; &apos;b&apos; then 2;;
(* Error: The constant 2 has type int
       but an expression was expected of type
         unit
       because it is in the result of a conditional with no else branch *)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The principle of name irrelavance: like $f(x)=x^2$ and $f(y )=y^2$, the name doesn&apos;t matter! so we just evaluate the expression according to the priority of parenthenses.
&amp;lt;font color=&quot;#ff0000&quot;&amp;gt;Rule: a new binding of a variable &lt;em&gt;shadows&lt;/em&gt; any old binding. &amp;lt;/font&amp;gt; It’s as if the new binding temporarily casts a shadow over the old binding. But eventually the old binding could reappear as the shadow recedes.of the variable name.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;let x = 5 in
  ((let x = 6 in x) + x);;
(* - : int = 11 *)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&amp;lt;font color=&quot;#ff0000&quot;&amp;gt;Shadowing is not mutable assignment.&amp;lt;/font&amp;gt; In the following example, each &lt;code&gt;let&lt;/code&gt; definition binds an entirely new variable. &amp;lt;font color=&quot;#f79646&quot;&amp;gt;If that new variable happens to have the same name as an old variable, the new variable temporarily shadows the old one.&amp;lt;/font&amp;gt; But the old variable is still around, and its value is immutable.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;let x = 42;;
(* val x : int = 42 *)
let f y = x + y;;
(* val f : int -&amp;gt; int = &amp;lt;fun&amp;gt; *)
f 0;;
(* : int = 42 *)
let x = 22;;
(* val x : int = 22 *)
f 0;;
(* - : int = 42  (* x did not mutate! *) *)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;OCaml has objects besides values like integers, tuples, lists, records, variants. Object oriented programming (OOP) in OCaml is available but rarely used. OOP organizes data (members and attributes) as objects and describes the object&apos;s behavior (methods or functions).&lt;/p&gt;
&lt;h3&gt;&lt;strong&gt;Definition&lt;/strong&gt;&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;let x = 42;;
(* val x: int = 42 *)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Definitions are not expressions&lt;/strong&gt;, nor are expressions definitions. But definitions can have expressions in the syntax.
&lt;code&gt;x&lt;/code&gt; is an identifier, which should starts with a lower-case letter.
&lt;code&gt;let x = e&lt;/code&gt;
Evaluation:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;evaluate expression &lt;code&gt;e&lt;/code&gt; to a value &lt;code&gt;v&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;bind &lt;code&gt;v&lt;/code&gt; to &lt;code&gt;x&lt;/code&gt; (a memory named &lt;code&gt;x&lt;/code&gt; contains &lt;code&gt;v&lt;/code&gt;)&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;&lt;strong&gt;Function&lt;/strong&gt;&lt;/h3&gt;
&lt;h5&gt;Auto type inference&lt;/h5&gt;
&lt;p&gt;We don&apos;t have to write types because the compiler does type inference according to the code itself. (But we can do annotations.)&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;let increment x = x + 1;;
(* val increment : int -&amp;gt; int = &amp;lt;fun&amp;gt; *)
let rec fact n = if n = 0 then 1 else n * fact (n - 1);;
(* val fact : int -&amp;gt; int = &amp;lt;fun&amp;gt; *)
let rec pow (x : int) (y : int) : int = if y = 0 then 1 else x * pow x (y-1);;
&lt;/code&gt;&lt;/pre&gt;
&lt;h5&gt;First-class functions&lt;/h5&gt;
&lt;p&gt;Functions are first-class citizens, having identifier &lt;code&gt;increment&lt;/code&gt;, and type &lt;code&gt;int -&amp;gt; int&lt;/code&gt;, and value as the function itself (utop prints &lt;code&gt;&amp;lt;fun&amp;gt;&lt;/code&gt; as a placeholder).
[[Notes from 1024th]]&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;let x = 1;;
(* val x : int = 1 *)
let f y = x + y;;
(* val f : int -&amp;gt; int = &amp;lt;fun&amp;gt; *)
let res1 = f 2 in (
    let x = 5 in (
    let res2 = f 2 in res1 + 10 * res2
  )
);;
(* Line 2, characters 8-9:
Warning 26 [unused-var]: unused variable x.

- : int = 33 *)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;f&lt;/code&gt; is a &lt;strong&gt;metavariable&lt;/strong&gt; indicating an identifier being used as a function name, and parameters &lt;code&gt;x&lt;/code&gt; are metavariables indicating argument identifiers.
These identifiers must begin with a lowercase letter.
When a function is defined, OCaml records that the name &lt;code&gt;f&lt;/code&gt; is bounded to a function with the given arguments.
OCaml functions don&apos;t have to have names. We can write a function &lt;code&gt;fun x -&amp;gt; x+1&lt;/code&gt; as a &quot;value&quot; just like we write a number &lt;code&gt;42&lt;/code&gt; (and this is also called lambda expression). The &lt;code&gt;let&lt;/code&gt; function definition is not an expression.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;let f1 x = x in (
let f2 x = x in (
f1 = f2 )
);;
(* Exception: Invalid_argument &quot;compare: functional value&quot;. *)

let f1 x = x in (
let f2 x = x in (
f1 == f2 )
);;
(* - : bool = false *)

let f1 x = x in (
let f2 = f1 in (
f1 == f2 )
);;
(* - : bool = true *)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&amp;lt;font color=&quot;#a5a5a5&quot;&amp;gt;&lt;code&gt;f1&lt;/code&gt; 和 &lt;code&gt;f2&lt;/code&gt; 都是函数（而且各自是不同的闭包值），OCaml 没有定义“两个函数是否相等”的通用语义：&amp;lt;/font&amp;gt;
&amp;lt;font color=&quot;#a5a5a5&quot;&amp;gt;- 扩展性问题：就算它们对所有输入返回一样（外延相等），一般也无法在有限时间内判定。&amp;lt;/font&amp;gt;
&amp;lt;font color=&quot;#a5a5a5&quot;&amp;gt;- 语义问题：闭包还可能捕获环境，是否“相等”也不清晰。 &amp;lt;/font&amp;gt;
&amp;lt;font color=&quot;#a5a5a5&quot;&amp;gt; 因此 OCaml 直接禁止用通用 &lt;code&gt;=&lt;/code&gt; 去比函数，并在运行时报错。&amp;lt;font color=&quot;#bfbfbf&quot;&amp;gt;(AIGC)&amp;lt;/font&amp;gt;&amp;lt;/font&amp;gt;&lt;a href=&quot;https://ocaml.org/docs/values-and-functions&quot;&gt;https://ocaml.org/docs/values-and-functions&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&amp;lt;font color=&quot;#a5a5a5&quot;&amp;gt;Now you have a taste of functions as first-class citizen. Higher-order programming is “more expressive for higher-order abstractions (callbacks, combinators, map/filter-style APIs) because passing behavior as a value is direct&quot; &amp;lt;font color=&quot;#bfbfbf&quot;&amp;gt;(AIGC)&amp;lt;/font&amp;gt;&amp;lt;/font&amp;gt;.&lt;a href=&quot;https://train.rse.ox.ac.uk/material/HPCu/software_architecture_and_design/functional/higher_order_functions_python&quot;&gt;train_rse.ox&lt;/a&gt;&lt;/p&gt;
&lt;h5&gt;Shadowing and scopes&lt;/h5&gt;
&lt;pre&gt;&lt;code&gt;let f x y = x + y;;
(* val f : int -&amp;gt; int -&amp;gt; int = &amp;lt;fun&amp;gt; *)
let f x y = x * y;;
(* val f : int -&amp;gt; int -&amp;gt; int = &amp;lt;fun&amp;gt; *)
f 3 3;;
(* - : int = 9 *)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This not mutable, just shadowing. When you write two functions with the same name, the latter one shadows the former one. And with &lt;code&gt;let ... in&lt;/code&gt; and &lt;code&gt;(...)&lt;/code&gt; to handle with scope, we can go beyond the shadowed scope and call the former one. (That&apos;s 1024th&apos;s example.) My experiments:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;let n = 10;;
(* val n : int = 10 *)

let f x = x + n;;
(* val f : int -&amp;gt; int = &amp;lt;fun&amp;gt; *)
f 5;;
(* - : int = 15 *)

let n = 20;;
(* val n : int = 20 *)

f 5;;
(* - : int = 15 *)

let f x= x + 3*n;;
(* val f : int -&amp;gt; int = &amp;lt;fun&amp;gt; *)
f 5;;
(* - : int = 65 *)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;An example from 1024th:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;let f x y = x + y in
let () =
(
  let f x y = x * y in
  Printf.printf &quot;%d\n&quot; (f 3 3)
) in
Printf.printf &quot;%d&quot; (f 3 3);;
(* 9
6- : unit = () *)
&lt;/code&gt;&lt;/pre&gt;
&lt;h5&gt;Mutually recursive functions&lt;/h5&gt;
&lt;blockquote&gt;
&lt;p&gt;&amp;lt;font color=&quot;#f79646&quot;&amp;gt;Mutually recursive functions&amp;lt;/font&amp;gt;: sometimes functions are mutually recursive, meaning that calls form a circle, where one function calls another which calls the first, with any number of calls in between.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;pre&gt;&lt;code&gt;let rec even n =
  n = 0 || odd (n - 1)
and odd n =
  n &amp;lt;&amp;gt; 0 &amp;amp;&amp;amp; even (n - 1);;
(* val even : int -&amp;gt; bool = &amp;lt;fun&amp;gt;
val odd : int -&amp;gt; bool = &amp;lt;fun&amp;gt; *)
&lt;/code&gt;&lt;/pre&gt;
&lt;h5&gt;Static and dynamic semantics&lt;/h5&gt;
&lt;p&gt;For functions with more than one arguments, they have &lt;code&gt;t1 -&amp;gt; t2 -&amp;gt; u&lt;/code&gt; as the type, meaning requiring two inputs, the first of type &lt;code&gt;t1&lt;/code&gt; and the second of type &lt;code&gt;t2&lt;/code&gt;, and returns an output of type &lt;code&gt;u&lt;/code&gt;.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;let f1 x y = x ^ y;;
(* val f1 : string -&amp;gt; string -&amp;gt; string = &amp;lt;fun&amp;gt; *)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Static semantics&lt;/strong&gt;: &lt;code&gt;e0 : t1 -&amp;gt; ... -&amp;gt; tn -&amp;gt; u&lt;/code&gt;, then &lt;code&gt;e1 : t1&lt;/code&gt; and .... &lt;code&gt;e0 e1 ... en: u&lt;/code&gt;.
&lt;strong&gt;Dynamic semantics&lt;/strong&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;To evaluate &lt;code&gt;e0 e1 ... en&lt;/code&gt;:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Evaluate &lt;code&gt;e0&lt;/code&gt; to a function. Also evaluate the argument expressions &lt;code&gt;e1&lt;/code&gt; through &lt;code&gt;en&lt;/code&gt; to values &lt;code&gt;v1&lt;/code&gt; through &lt;code&gt;vn&lt;/code&gt;.
For &lt;code&gt;e0&lt;/code&gt;, the result might be an anonymous function &lt;code&gt;fun x1 ... xn -&amp;gt; e&lt;/code&gt; or a name &lt;code&gt;f&lt;/code&gt;. In the latter case, we need to find the definition of &lt;code&gt;f&lt;/code&gt;, which we can assume to be of the form &lt;code&gt;let rec f x1 ... xn = e&lt;/code&gt;. Either way, we now know the argument names &lt;code&gt;x1&lt;/code&gt; through &lt;code&gt;xn&lt;/code&gt; and the body &lt;code&gt;e&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Substitute each value &lt;code&gt;vi&lt;/code&gt; for the corresponding argument name &lt;code&gt;xi&lt;/code&gt; in the body &lt;code&gt;e&lt;/code&gt; of the function. That substitution results in a new expression &lt;code&gt;e&apos;&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Evaluate &lt;code&gt;e&apos;&lt;/code&gt; to a value &lt;code&gt;v&lt;/code&gt;, which is the result of evaluating &lt;code&gt;e0 e1 ... en&lt;/code&gt;.
If you compare these evaluation rules to the rules for &lt;code&gt;let&lt;/code&gt; expressions, you will notice they both involve &amp;lt;font color=&quot;#f79646&quot;&amp;gt;substitution&amp;lt;/font&amp;gt;. This is not an accident. In fact, anywhere &lt;code&gt;let x = e1 in e2&lt;/code&gt; appears in a program, we could replace it with &lt;code&gt;(fun x -&amp;gt; e2) e1&lt;/code&gt;. They are syntactically different but semantically equivalent. In essence, &amp;lt;font color=&quot;#f79646&quot;&amp;gt;&lt;code&gt;let&lt;/code&gt; expressions are just syntactic sugar for anonymous function application&amp;lt;/font&amp;gt;.&lt;/li&gt;
&lt;/ol&gt;
&lt;/blockquote&gt;
&lt;h5&gt;&amp;lt;font color=&quot;#ff0000&quot;&amp;gt;Polymorphism&amp;lt;/font&amp;gt;&lt;/h5&gt;
&lt;p&gt;And when the functions without annotations can be adapted to multiple types, it will be written as a an unknown type &lt;code&gt;&apos;a&lt;/code&gt;. And you can assign this function to another function with type specified.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;We took a value of type &lt;code&gt;&apos;a -&amp;gt; &apos;a&lt;/code&gt;, and we bound it to a name whose type was manually specified as being &lt;code&gt;int -&amp;gt; int&lt;/code&gt;. This assignment is possible because it doesn&apos;t break the promise of &lt;code&gt;id&lt;/code&gt; or the anonymous &lt;code&gt;fun x -&amp;gt; x&lt;/code&gt;, it just loses some information. It’s always going to be &amp;lt;font color=&quot;#f79646&quot;&amp;gt;safe&amp;lt;/font&amp;gt; to use a function of type &lt;code&gt;&apos;a -&amp;gt; &apos;a&lt;/code&gt; when what we needed was a function of type &lt;code&gt;int -&amp;gt; int&lt;/code&gt;.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;pre&gt;&lt;code&gt;let id x = x;;
(* val id : &apos;a -&amp;gt; &apos;a = &amp;lt;fun&amp;gt; *)

let id2 : &apos;a -&amp;gt; &apos;a = fun x -&amp;gt; x;;
(* val id2 : &apos;a -&amp;gt; &apos;a = &amp;lt;fun&amp;gt; (* manually annotate to a general type *) *)

let id_int : int -&amp;gt; int = id;;
(* val id_int : int -&amp;gt; int = &amp;lt;fun&amp;gt; *)

let id_bool : bool -&amp;gt; bool = fun x -&amp;gt; x;;
(* val id_bool : bool -&amp;gt; bool = &amp;lt;fun&amp;gt; *)

let first x y = x;;
(* val first : &apos;a -&amp;gt; &apos;b -&amp;gt; &apos;a = &amp;lt;fun&amp;gt; *)

let first_int : int -&amp;gt; &apos;a -&amp;gt; int = first;;
(* val first_int : int -&amp;gt; &apos;a -&amp;gt; int = &amp;lt;fun&amp;gt; *)

let first_str : string -&amp;gt; &apos;a -&amp;gt; int = first;;
(* Error: The value first has type
         string -&amp;gt; &apos;a -&amp;gt; string
       but an expression was expected of type
         string -&amp;gt; &apos;a -&amp;gt; int
       Type string is not compatible with type int *)
&lt;/code&gt;&lt;/pre&gt;
&lt;h5&gt;Labelled arguments&lt;/h5&gt;
&lt;p&gt;You can also lable the arguments with &lt;code&gt;~name:&lt;/code&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;let first_str : string -&amp;gt; &apos;a -&amp;gt; int = first;;
(* Error: The value first has type
         string -&amp;gt; &apos;a -&amp;gt; string
       but an expression was expected of type
         string -&amp;gt; &apos;a -&amp;gt; int
       Type string is not compatible with type int *)

let sum ~lchild:x ~rchild:y = x + y;;
(* val sum : lchild:int -&amp;gt; rchild:int -&amp;gt; int = &amp;lt;fun&amp;gt; *)

sum 7 8;;
(* Without specifying the names, there will be warnings *)
(* Line 1, characters 0-3:
Warning 6 [labels-omitted]: labels lchild, rchild were omitted in the application of this function.

Line 1, characters 0-3:
Warning 6 [labels-omitted]: labels lchild, rchild were omitted in the application of this function.

- : int = 15 *)

sum ~lchild:4 ~rchild:5;;
(* - : int = 9 *)

let echo ~str:(x : string) = x;;
(* val echo : str:string -&amp;gt; string = &amp;lt;fun&amp;gt; *)
&lt;/code&gt;&lt;/pre&gt;
&lt;h5&gt;Optional arguments&lt;/h5&gt;
&lt;p&gt;Optional argument with default value. Then the name of the optional argument cannot be skipped.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt; let step ?default_arg: (x=1) y = x + y;;
(* val step : ?default_arg:int -&amp;gt; int -&amp;gt; int = &amp;lt;fun&amp;gt; *)

step 2 0;;
(* Error: The function applied to this argument has type
         ?default_arg:int -&amp;gt; int
This argument cannot be applied without label *)

step ~default_arg:2 0;;
(* - : int = 2 *)
step 0;;
(* - : int = 1 *)
&lt;/code&gt;&lt;/pre&gt;
&lt;h5&gt;Partial application&lt;/h5&gt;
&lt;p&gt;OCaml allows partial application.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;let add x = fun y -&amp;gt; x + y;;
(* val add : int -&amp;gt; int -&amp;gt; int = &amp;lt;fun&amp;gt;
   (* Semantically equivalent to `let add x y = x + y` *)
   (* Also equivalent to `let add = fun x -&amp;gt; (fun y -&amp;gt; x + y)` *) *)
addx 5;;
(* - : int -&amp;gt; int = &amp;lt;fun&amp;gt; *)
&lt;/code&gt;&lt;/pre&gt;
&lt;h5&gt;Functiona Associativity&lt;/h5&gt;
&lt;p&gt;&amp;lt;font color=&quot;#ff0000&quot;&amp;gt;Every OCaml function takes exactly one argument.&amp;lt;/font&amp;gt;
Even though you think of &lt;code&gt;f&lt;/code&gt; as a function that takes &lt;code&gt;n&lt;/code&gt; arguments, in reality it is a function that takes 1 argument and returns a function. The type of a function should be &lt;code&gt;t1 -&amp;gt; (t2 -&amp;gt; (t3 -&amp;gt; t4))&lt;/code&gt;, which is, function types are &amp;lt;font color=&quot;#f79646&quot;&amp;gt;right associative&amp;lt;/font&amp;gt;: there are implicit parentheses around function types, from right to left. The intuition here is that a function takes a single argument and returns a new function that expects the remaining arguments.
Function application, on the other hand, is &amp;lt;font color=&quot;#f79646&quot;&amp;gt;left associative&amp;lt;/font&amp;gt;, where &lt;code&gt;e1 e2 e3 e4&lt;/code&gt; is acutally &lt;code&gt;((e1 e2) e3) e4&lt;/code&gt;.&lt;/p&gt;
&lt;h5&gt;Define new operators&lt;/h5&gt;
&lt;p&gt;Built-in infix operators are acutally implemented as functions.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;let ( ^^ ) x y = max x y
&lt;/code&gt;&lt;/pre&gt;
&lt;h5&gt;Pipelines&lt;/h5&gt;
&lt;pre&gt;&lt;code&gt;let inc x = x + 1;;
(* val inc : int -&amp;gt; int = &amp;lt;fun&amp;gt; *)
let square x = x * x;;
(* val square : int -&amp;gt; int = &amp;lt;fun&amp;gt; *)
inc (square 6);;
(* - : int = 37 *)
6 |&amp;gt; square |&amp;gt; inc;;
(* - : int = 37 *)
&lt;/code&gt;&lt;/pre&gt;
&lt;h5&gt;Tail-call optimization&lt;/h5&gt;
&lt;p&gt;OCaml also implement function calls in a stack.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;let rec count n =
  if n = 0 then 0 else 1 + count (n - 1);;

let rec count_aux n acc =
  if n = 0 then acc else count_aux (n - 1) (acc + 1);;
let count_tr n = count_aux n 0;; (* tr for tail recursion *)
&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote&gt;
&lt;p&gt;A good compiler (and the OCaml compiler is good this way) can notice when a recursive call is in &lt;em&gt;tail position&lt;/em&gt;,&amp;lt;font color=&quot;#f79646&quot;&amp;gt; which is a technical way of saying “there’s no more computation to be done after it returns”.&amp;lt;/font&amp;gt; &lt;strong&gt;A recursive call in tail position does not need a new stack frame. It can just reuse the existing stack frame.&lt;/strong&gt; That’s because there’s nothing left of use in the existing stack frame. None of that memory ever needs to be read again, because that call is effectively already finished.
This is the &lt;em&gt;tail-call optimization&lt;/em&gt;. It can even be applied in cases beyond recursive functions if &amp;lt;font color=&quot;#f79646&quot;&amp;gt;the calling function’s stack frame is suitably compatible with the callee.&amp;lt;/font&amp;gt; &amp;gt; &lt;strong&gt;The Recipe for Tail Recursion.&lt;/strong&gt; In a nutshell, here’s how we made a function be tail recursive:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Change the function into a helper function. Add an extra argument: the accumulator, often named &lt;code&gt;acc&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Write a new “main” version of the function that calls the helper. It passes the original base case’s return value as the initial value of the accumulator.&lt;/li&gt;
&lt;li&gt;Change the helper function to return the accumulator in the base case.&lt;/li&gt;
&lt;li&gt;Change the helper function’s recursive case. It now needs to do the extra work on the accumulator argument, before the recursive call. This is the only step that requires much ingenuity.&lt;/li&gt;
&lt;/ol&gt;
&lt;/blockquote&gt;
&lt;h3&gt;Directives&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;#use &quot;somefile.ml&quot;;; (* in order to load codes in toplevel *)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Exit utop when you want to edit the code in the &lt;code&gt;#use&lt;/code&gt; file, because utop runs a single-thread, reloading might cause type-checking error or memory leak.&lt;/p&gt;
&lt;h3&gt;Documentation&lt;/h3&gt;
&lt;p&gt;todo&lt;/p&gt;
&lt;h3&gt;Lists&lt;/h3&gt;
&lt;p&gt;OCaml list is a sequence of values with the same type, implemented as singly-linked lists. (Suprising name! Yes, linked list: singly linked lists and doubly linked lists).
So their implementation is good for sequential access.
&lt;code&gt;[e1; e2]&lt;/code&gt; is syntatic sugar for &lt;code&gt;e1 :: e2 :: []&lt;/code&gt;, consing elements to the nil.
Cons is a right associative operator.
&lt;code&gt;[]&lt;/code&gt; is a value. To evaluate &lt;code&gt;e1 :: e2&lt;/code&gt;, we first evaluate &lt;code&gt;e1&lt;/code&gt; to be value &lt;code&gt;v1&lt;/code&gt;, and evaluated &lt;code&gt;e2&lt;/code&gt; to be a list value &lt;code&gt;v2&lt;/code&gt;, and then return a &lt;strong&gt;new&lt;/strong&gt; list value &lt;code&gt;v1 :: v2&lt;/code&gt;. So the cons will have the same list type of &lt;code&gt;e2&lt;/code&gt;, and require the prepended element to have type the same as the list elements in &lt;code&gt;e2&lt;/code&gt;. If the elements in the list are type &lt;code&gt;t&lt;/code&gt;, then the list will be &lt;code&gt;t list&lt;/code&gt;.
Lists are first-class citizens. They are immutable. so the &lt;code&gt;::&lt;/code&gt; doesn&apos;t change the list, it creates a new one by prepending.
Immutability it safe for the compiler to perform an optimization. Two lists, if one derived from another, can share some of the memory for optimization and do this safely because they both don&apos;t change.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;Compare:&lt;/strong&gt;&lt;/em&gt;
Cons &lt;code&gt;::&lt;/code&gt; does prepend &lt;code&gt;&apos;a -&amp;gt; &apos;a list -&amp;gt; &apos;a list&lt;/code&gt;. Constant time.
Append &lt;code&gt;@&lt;/code&gt; does combination &lt;code&gt;&apos;a list-&amp;gt; &apos;a list -&amp;gt; &apos;a list&lt;/code&gt;. Linear time of the first list.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;[];; (* `[]` type is not determined, `[]` pronounced as nil *)
(* - : &apos;a list = [] *)
[1];;
(* - : int list =  *)
[1; 2];;
(* - : int list = [1; 2] *)
[1; 1.];;
(* Error: The constant 1. has type float
       but an expression was expected of type int *)
[[1];[2]];;
(* - : int list list = [; ] *)
1 :: 2 :: [];; (* pronounced as cons*)
(* - : int list = [1; 2] *)
&quot;red&quot; :: [&quot;blue&quot;; &quot;green&quot;];;
(* - : string list = [&quot;red&quot;; &quot;blue&quot;; &quot;green&quot;] *)
&lt;/code&gt;&lt;/pre&gt;
&lt;h5&gt;Pattern Matching&lt;/h5&gt;
&lt;pre&gt;&lt;code&gt;match not true with | true -&amp;gt; &quot;nope&quot; | false -&amp;gt; &quot;yep&quot;;;
(* - : string = &quot;yep&quot; *)

let y = match 42 with foo -&amp;gt; foo;;
(* val y : int = 42 *)

let z = match &quot;hello&quot; with | &quot;foo&quot; -&amp;gt; 1 | _ -&amp;gt; 2;;
(* val z : int = 2 *)

let a = match [] with | [] -&amp;gt; &quot;empty&quot; | _ -&amp;gt; &quot;not empty&quot;;;
(* val a : string = &quot;empty&quot; *)

let b = match [&quot;111&quot;; &quot;222&quot;] with | [] -&amp;gt; &quot;empty list&quot; | head :: tail -&amp;gt; head;;
(* val b : string = &quot;111&quot; *)

let b = match [&quot;111&quot;; &quot;222&quot;] with | [] -&amp;gt; [&quot;empty list&quot;] | head :: tail -&amp;gt; head;;
(* Error: The value head has type string
       but an expression was expected of type
         string list *)

let first3 t =
 match t with | (a, b, c) -&amp;gt; a;;
(* val first3 : &apos;a * &apos;b * &apos;c -&amp;gt; &apos;a = &amp;lt;fun&amp;gt; *)

first3 (1, 2, 3);;
(* - : int = 1 *)

fst (1, 2);;
(* - : int = 1 *)

type student = {
 name : string;
 year: int;
}

let rgb = {
 name = &quot;ruth&quot;;
 year = 1111;
}

let name_with_year s = match s with
 | {name; year} -&amp;gt; name ^ &quot; &quot; ^ string_of_int year;;
(* type student = { name : string; year : int; }
val rgb : student =
  {name = &quot;ruth&quot;; year = 1111}
val name_with_year : student -&amp;gt; string = &amp;lt;fun&amp;gt; *)

name_with_year rgb;;
(* - : string = &quot;ruth 1111&quot; *)

let test lst = (* let empty lst = (lst = []) *)
    match lst with
    | [] -&amp;gt; true
    | h :: t -&amp;gt; false;;
(* val test : &apos;a list -&amp;gt; bool = &amp;lt;fun&amp;gt; *)

test [];;
(* - : bool = true *)
test [&quot;aimme&quot;; &quot;cat&quot;];;
(* - : bool = false *)

let test lst =
    match lst with
    | [] -&amp;gt; true
    | _ :: _ -&amp;gt; false;;
(* val test : &apos;a list -&amp;gt; bool = &amp;lt;fun&amp;gt; *)

let rec sum lst =
    match lst with
    | [] -&amp;gt; 0
    | h :: t -&amp;gt; h + sum t;;
(* val sum : int list -&amp;gt; int = &amp;lt;fun&amp;gt; *)

sum [1; 2; 3; 4; 5];;
(* - : int = 15 *)

#trace sum;;
(* sum is now traced. *)

sum [1; 2; 3;];;
(* sum &amp;lt;-- [1; 2; 3]
sum &amp;lt;-- [2; 3]
sum &amp;lt;-- [3]
sum &amp;lt;-- []
sum --&amp;gt; 0
sum --&amp;gt; 3
sum --&amp;gt; 5
sum --&amp;gt; 6
- : int = 6 *)

#untrace sum;;
(* sum is no longer traced. *)

let rec append lst1 lst2 =
    match lst1 with
    | [] -&amp;gt; lst2
    | h :: t -&amp;gt; h :: append t lst2;;
(* val append : &apos;a list -&amp;gt; &apos;a list -&amp;gt; &apos;a list =
  &amp;lt;fun&amp;gt; *)

append [1; 2] [3; 4; 5];;
(* - : int list = [1; 2; 3; 4; 5] *)
append [1; 2] [];;
(* - : int list = [1; 2] *)

[1; 2] @ [3; 4];;
(* - : int list = [1; 2; 3; 4] *)

List.hd [1.; 2.; 3.;];;
(* - : float = 1. *)
List.tl [1.; 2.; 3.;];;
(* - : float list = [2.; 3.] *)
List.hd [];;
(* Exception: Failure &quot;hd&quot;. (* pattern matching is more robust, handling with empty list. *) *)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Like switch statement in C++, but more powerful.
Match with some &lt;strong&gt;shapes&lt;/strong&gt; of data, and then extract pieces from the data.
Lists are not mutable. Immutable.&lt;/p&gt;
&lt;p&gt;Syntacs: here &lt;code&gt;p&lt;/code&gt;&amp;lt;font color=&quot;#f79646&quot;&amp;gt; is pattern expressions&amp;lt;/font&amp;gt; (like any identifier, &lt;code&gt;_&lt;/code&gt;, any constant value, &lt;code&gt;[]&lt;/code&gt;, &lt;code&gt;p1 :: p2&lt;/code&gt;, &lt;code&gt;(p1, p2)&lt;/code&gt;, &lt;code&gt;{f1=p1; f2=p2}&lt;/code&gt;)&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;match e with
| p1 -&amp;gt; e1
| p2 -&amp;gt; e2
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Semantics (evaluation)&lt;/strong&gt;:
First evaluate &lt;code&gt;e&lt;/code&gt; to &lt;code&gt;v&lt;/code&gt;, and find the first pattern &lt;code&gt;pi&lt;/code&gt; (top to bottom) that matches &lt;code&gt;v&lt;/code&gt;, then evaluate &lt;code&gt;ei&lt;/code&gt; to &lt;code&gt;vi&lt;/code&gt; and return &lt;code&gt;vi&lt;/code&gt;.
&lt;em&gt;&lt;strong&gt;Patterns&lt;/strong&gt;&lt;/em&gt;: A constant matches itself. &amp;lt;font color=&quot;#f79646&quot;&amp;gt;An identifier matches anything and binds itself (the name) with the matched value in the scope of the branch. &amp;lt;/font&amp;gt;The underscore matches anything and doesn&apos;t bind.&lt;/p&gt;
&lt;blockquote&gt;
&lt;ul&gt;
&lt;li&gt;If &lt;code&gt;p1&lt;/code&gt; matches &lt;code&gt;v1&lt;/code&gt; and produces a set of bindings, and if &lt;code&gt;p2&lt;/code&gt; matches &lt;code&gt;v2&lt;/code&gt; and produces a set of bindings, then &lt;code&gt;p1 :: p2&lt;/code&gt; matches &lt;code&gt;v1 :: v2&lt;/code&gt; and produces the union set of bindings. Note that &lt;code&gt;v2&lt;/code&gt; must be a list (since it’s on the right-hand side of &lt;code&gt;::&lt;/code&gt;) and could have any length. Note that the union of bindings will never have a problem where the same variable is bound separately in two bindings and because of &amp;lt;font color=&quot;#f79646&quot;&amp;gt;the syntactic restriction that no variable name may appear more than once in a pattern. &amp;lt;/font&amp;gt;&lt;/li&gt;
&lt;li&gt;If for all &lt;code&gt;i&lt;/code&gt; in &lt;code&gt;1..n&lt;/code&gt;, it holds that &lt;code&gt;pi&lt;/code&gt; matches &lt;code&gt;vi&lt;/code&gt; and produces the set of bindings, then &lt;code&gt;[p1; ...; pn]&lt;/code&gt; matches &lt;code&gt;[v1; ...; vn]&lt;/code&gt; and produces a set of bindings. Note that this pattern specifies the exact length the list must be.&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;
&lt;p&gt;Type-checking (static): all of the patterns and the value that will be matched should the same type. All the expressions in branches should have the same type, and this will be the type of the entire match expression.
And the compiler also tests &lt;em&gt;&lt;strong&gt;exhaustiveness/exhaustivity&lt;/strong&gt;&lt;/em&gt; and &lt;em&gt;&lt;strong&gt;unused branches&lt;/strong&gt;&lt;/em&gt;.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;let bad_test lst =
    match lst with
    | [] -&amp;gt; &quot;empty&quot;;;

(* Lines 2-3, characters 4-19:
Warning 8 [partial-match]: this pattern-matching is not exhaustive.
Here is an example of a case that is not matched:
_::_

val bad_test : &apos;a list -&amp;gt; string = &amp;lt;fun&amp;gt; *)

let rec sum lst =
  match lst with
  | h :: t -&amp;gt; h + sum t
  | [ h ] -&amp;gt; h
  | [] -&amp;gt; 0;;
(* Line 4, characters 4-9:
Warning 11 [redundant-case]: this match case is unused.

val sum : int list -&amp;gt; int = &amp;lt;fun&amp;gt; *)

(* A silly example where the programmer thought the code will check whether n is equal to n. But pattern matching is not checking equality, it matches an identifer pattern with `n`, so it will be always true. Therefore the second branch is unused.*)
let length_is lst n =
  match List.length lst with
  | n -&amp;gt; true
  | _ -&amp;gt; false;;
(* Line 4, characters 4-5:
Warning 11 [redundant-case]: this match case is unused.

val length_is : &apos;a list -&amp;gt; &apos;b -&amp;gt; bool = &amp;lt;fun&amp;gt; *)
&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;_ :: []&lt;/code&gt; matches all lists with exactly one element&lt;/li&gt;
&lt;li&gt;&lt;code&gt;_ :: _&lt;/code&gt; matches all lists with at least one element&lt;/li&gt;
&lt;li&gt;&lt;code&gt;_ :: _ :: []&lt;/code&gt; matches all lists with exactly two elements&lt;/li&gt;
&lt;li&gt;&lt;code&gt;_ :: _ :: _ :: _&lt;/code&gt; matches all lists with at least three elements&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;
&lt;h5&gt;Syntatic sugar for function keyword&lt;/h5&gt;
&lt;p&gt;We can skip the last argument and the &lt;code&gt;match with&lt;/code&gt; thing if we are doing a pattern matching for the last argument. So here is a rewriting of &lt;code&gt;sum&lt;/code&gt;.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;let f x y z = match z with
    | [] -&amp;gt; x + y
    | _ -&amp;gt; 0;;
(* val f : int -&amp;gt; int -&amp;gt; &apos;a list -&amp;gt; int = &amp;lt;fun&amp;gt; *)
let f1 x y = function
    | [] -&amp;gt; x + y
    | _ -&amp;gt; 0;;
(* val f1 : int -&amp;gt; int -&amp;gt; &apos;a list -&amp;gt; int = &amp;lt;fun&amp;gt; *)
f 2 3 [];;
(* - : int = 5 *)
f1 2 3 [];;
(* - : int = 5 *)

let rec sum = function
    | [] -&amp;gt; 0
    | h :: t -&amp;gt; h + sum t;;
(* val sum : int list -&amp;gt; int = &amp;lt;fun&amp;gt; *)
sum [2; 3];;
(* - : int = 5 *)
&lt;/code&gt;&lt;/pre&gt;
</content:encoded><author>Shen, 1024th</author></item></channel></rss>