mirror of
https://github.com/hmemcpy/milewski-ctfp-pdf.git
synced 2024-10-04 01:27:28 +03:00
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:
parent
964d971ceb
commit
67b94c43b9
@ -1,6 +1 @@
|
||||
module type Polymorphic_Function_F = sig
|
||||
type a
|
||||
type b
|
||||
|
||||
val f : a -> b
|
||||
end
|
||||
val f : a -> b
|
||||
|
@ -1,6 +1 @@
|
||||
module type Polymorphic_Function_G = sig
|
||||
type b
|
||||
type c
|
||||
|
||||
val g : b -> c
|
||||
end
|
||||
val g : b -> c
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -1,2 +1,2 @@
|
||||
f >> id
|
||||
id >> f
|
||||
f % id = f
|
||||
id % f = f
|
||||
|
@ -1,3 +1 @@
|
||||
module type Chapter2_DeclareVariable = sig
|
||||
val x : int
|
||||
end
|
||||
val x : int
|
||||
|
@ -1 +0,0 @@
|
||||
let unit _ = ()
|
@ -1,3 +0,0 @@
|
||||
type bool =
|
||||
| false
|
||||
| true
|
@ -1,3 +1 @@
|
||||
module type Chapter2_DeclareFunction = sig
|
||||
val f : bool -> bool
|
||||
end
|
||||
val f : bool -> bool
|
||||
|
@ -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"
|
||||
|
@ -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"
|
||||
|
@ -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)
|
||||
|
@ -1,3 +1,2 @@
|
||||
type void
|
||||
|
||||
let rec absurd (x : void) = absurd x
|
||||
val absurd : void -> 'a
|
||||
|
@ -1 +1,2 @@
|
||||
let f44 () : int = 44
|
||||
(* val f44 : unit -> int *)
|
||||
let f44 () = 44
|
||||
|
@ -1 +1,2 @@
|
||||
let f_int (x : int) = ()
|
||||
(* val f_int : int -> unit *)
|
||||
let f_int x = ()
|
||||
|
@ -1 +1,2 @@
|
||||
let f_int (_ : int) = ()
|
||||
(* val f_int :: int -> unit *)
|
||||
let f_int _ = ()
|
||||
|
@ -1 +1,2 @@
|
||||
(* val unit : 'a -> unit *)
|
||||
let unit _ = ()
|
||||
|
@ -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
|
||||
|
@ -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 = ( ^ )
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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, ""
|
||||
|
@ -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 "
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user