Make OCaml code samples closer to Haskell (chapters 1 to 4)

- Get rid of module declarations
- Use only OCaml Stdlib
- Rename composition operator to `(%)` due to operator precedence issues
This commit is contained in:
Yawar Amin 2020-02-20 00:12:42 -05:00
parent 964d971ceb
commit 67b94c43b9
24 changed files with 65 additions and 86 deletions

View File

@ -1,6 +1 @@
module type Polymorphic_Function_F = sig
type a
type b
val f : a -> b
end
val f : a -> b

View File

@ -1,6 +1 @@
module type Polymorphic_Function_G = sig
type b
type c
val g : b -> c
end
val g : b -> c

View File

@ -1,9 +1,3 @@
module Compose_Example
(F : Polymorphic_Function_F)
(G : Polymorphic_Function_G with type b = F.b) =
struct
(** OCaml doesn't have a compose operator. So, creating one. **)
let ( >> ) g f x = g (f x)
let compose : 'a -> 'c = G.g >> F.f
end
(** OCaml doesn't have a compose operator. So, creating one. **)
let ( % ) g f x = g (f x)
g % f

View File

@ -1,9 +1,5 @@
module Compose_Three_GF = functor(F:Polymorphic_Function_F)(G:Polymorphic_Function_G with type b = F.b)(H:Polymorphic_Function_H with type c = G.c) -> struct
let compose : 'a -> 'd = H.h >> (G.g >> F.f)
end
val f : a -> b
val g : b -> c
val h : c -> d
module Compose_Three_HG = functor(F:Polymorphic_Function_F)(G:Polymorphic_Function_G with type b = F.b)(H:Polymorphic_Function_H with type c = G.c) -> struct
let compose : 'a -> 'd = (H.h >> G.g) >> F.f
end
Compose_Three_GF.compose = Compose_Three_HG.compose
h % (g % f) = (h % g) % f = h % g % f

View File

@ -1,2 +1,2 @@
f >> id
id >> f
f % id = f
id % f = f

View File

@ -1,3 +1 @@
module type Chapter2_DeclareVariable = sig
val x : int
end
val x : int

View File

@ -1 +0,0 @@
let unit _ = ()

View File

@ -1,3 +0,0 @@
type bool =
| false
| true

View File

@ -1,3 +1 @@
module type Chapter2_DeclareFunction = sig
val f : bool -> bool
end
val f : bool -> bool

View File

@ -1,3 +1,2 @@
module Chapter2_Bottom : Chapter2_DeclareFunction = struct
let f (b : bool) : bool = failwith "Not Implemented"
end
(* val f : bool -> bool *)
let f _x = failwith "Not Implemented"

View File

@ -1,3 +1,2 @@
module Chapter2_Bottom : Chapter2_DeclareFunction = struct
let f : bool -> bool = fun _ -> failwith "Not implemented"
end
(* val f : bool -> bool *)
let f = failwith "Not Implemented"

View File

@ -1 +1,14 @@
let fact n = List.fold (List.range 1 n) ~init:1 ~f:( * )
(* OCaml doesn't ship with a lazy sequence range syntax nor a product
function; defining our own. *)
let rec range seq n1 n2 =
if n2 < n1 then seq
else n2 |> pred |> range (fun () -> Seq.Cons (n2, seq)) n1
let range = range Seq.empty
let rec product result seq = match seq () with
| Seq.Nil -> result
| Seq.Cons (n, seq) -> product (result * n) seq
let product = product 1
let fact n = product (range 1 n)

View File

@ -1,3 +1,2 @@
type void
let rec absurd (x : void) = absurd x
val absurd : void -> 'a

View File

@ -1 +1,2 @@
let f44 () : int = 44
(* val f44 : unit -> int *)
let f44 () = 44

View File

@ -1 +1,2 @@
let f_int (x : int) = ()
(* val f_int : int -> unit *)
let f_int x = ()

View File

@ -1 +1,2 @@
let f_int (_ : int) = ()
(* val f_int :: int -> unit *)
let f_int _ = ()

View File

@ -1 +1,2 @@
(* val unit : 'a -> unit *)
let unit _ = ()

View File

@ -1,6 +1,6 @@
module type Monoid = sig
type a
module type MONOID = sig
type t
val mempty : a
val mappend : a -> a -> a
val mempty : t
val mappend : t -> t -> t
end

View File

@ -1,6 +1,8 @@
module StringMonoid : Monoid = struct
type a = string
(* In OCaml, any module that defines a module type's members,
automatically conforms to that module type. It doesn't need to
explicitly declare that it conforms. *)
let mempty = ""
let mappend = ( ^ )
end
type t = string
let mempty = ""
let mappend = ( ^ )

View File

@ -1,7 +1 @@
module type Kleisli = sig
type a
type b
type c
val ( >=> ) : (a -> b writer) -> (b -> c writer) -> a -> c writer
end
val ( >=> ) : ('a -> 'b writer) -> ('b -> 'c writer) -> 'a -> 'c writer

View File

@ -1 +1,4 @@
let pure x = x, ""
let ( >=> ) m1 m2 = fun x ->
let y, s1 = m1 x in
let z, s2 = m2 y in
z, s1 ^ s2

View File

@ -1,3 +1,2 @@
let up_case : string -> string writer =
fun s -> String.uppercase s, "up_case "
;;
(* val return : 'a -> 'a writer *)
let return x = x, ""

View File

@ -1,3 +1,6 @@
let to_words : string -> string list writer =
fun s -> String.split s ~on:' ', "to_words "
;;
(* val up_case : string -> string writer
Note: OCaml strings are raw bytestrings, not UTF-8 encoded. *)
let up_case s = String.uppercase_ascii s, "up_case "
(* val to_words : string -> string list writer *)
let to_words s = String.split_on_char ' ' s, "to_words "

View File

@ -1,10 +1,2 @@
module KleisiExample
(K : Kleisli
with type a = string
and type b = string
and type c = string list) =
struct
let up_case_and_to_words : string -> string list writer =
K.( >=> ) up_case to_words
;;
end
(* val process : string -> string list writer *)
let process = up_case >=> to_words