-
Notifications
You must be signed in to change notification settings - Fork 0
/
it_Ops.ml
166 lines (139 loc) · 4.78 KB
/
it_Ops.ml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
(** пропустить значение последовательно через функции:
123 >> string_of_int >> print_string
*)
let ( >> ) x f = f x
(** применить значение к функции:
print_string & string_of_int & 123
NB: оператор "&" является ключевым словом в jocaml
Если попробовать объявить "let ( $ ) f x = f x",
то полученный оператор будет левоассоциативным,
что нежелательно в данном случае.
*)
let ( & ) f x = f x
(** композиция функций:
let print_int = print_string % string_of_int
let print_int = print_string $ string_of_int
let print_int_sum = print_string % string_of_int %% ( + )
let print_int_sum = print_string %% (string_of_int %% ( + ) )
let for_all pred = not % List.exists (not % pred)
let for_all2 pred = not %% List.exists2 (not %% pred)
Операторы левоассоциативны, у оператора ($) приоритет ниже,
чем у (%), и ниже, чем у арифметических операторов.
*)
let ( % ) f g = fun x -> f (g x)
let ( $ ) = ( % )
let ( %% ) f g = fun x y -> f (g x y)
let ( %%% ) f g = fun x y z -> f (g x y z)
(** применить инфиксную функцию:
123L /* Int64.add */ 234L
*)
let ( /* ) x y = y x
let ( */ ) x y = x y
(* Для удобного использования инфиксных операторов
существует отличное решение: pa_do
( http://pa-do.forge.ocamlcore.org/ )
Если использовать его не можете, то в качестве
слабого подобия можно взять нижеследующие модули.
Их названия имеют вид "Тип1_as_тип2", и при открытии
такого модуля со значениями типа1 можно будет работать
теми операторами, которыми обычно работают со значениями
типа2.
Например,
let my_int64 =
let module M =
struct
open Int32_as_int
open Int64_as_float
let x = (Int64.of_int32 (123l + 234l)) +. 345L
end
in
M.x
*)
(* Замечание: для консистентности модули "Тип1_as_тип2"
всегда должны переопределять одни и те же операторы.
*)
(* todo: добавить в Int* операции mod, rem, битовые *)
module Int_as_int =
struct
let ( + ) = Pervasives.( + )
let ( - ) = Pervasives.( - )
let ( * ) = Pervasives.( * )
let ( / ) = Pervasives.( / )
let ( ~- ) = Pervasives.( ~- )
end
module Float_as_float =
struct
let ( +. ) = Pervasives.( +. )
let ( -. ) = Pervasives.( -. )
let ( *. ) = Pervasives.( *. )
let ( /. ) = Pervasives.( /. )
let ( ~-. ) = Pervasives.( ~-. )
end
(** TODO core, pa_do, pa_openin *)
module Int32_as_int =
struct
let ( + ) = Int32.add
let ( - ) = Int32.sub
let ( * ) = Int32.mul
let ( / ) = Int32.div
let ( ~- ) = Int32.neg
end
module Int64_as_int =
struct
let ( + ) = Int64.add
let ( - ) = Int64.sub
let ( * ) = Int64.mul
let ( / ) = Int64.div
let ( ~- ) = Int64.neg
end
module Int_as_float =
struct
let ( +. ) = Pervasives.( + )
let ( -. ) = Pervasives.( - )
let ( *. ) = Pervasives.( * )
let ( /. ) = Pervasives.( / )
let ( ~-. ) = Pervasives.( ~- )
end
module Float_as_int =
struct
let ( + ) = Pervasives.( +. )
let ( - ) = Pervasives.( -. )
let ( * ) = Pervasives.( *. )
let ( / ) = Pervasives.( /. )
let ( ~- ) = Pervasives.( ~-. )
end
module Int32_as_float =
struct
let ( +. ) = Int32.add
let ( -. ) = Int32.sub
let ( *. ) = Int32.mul
let ( /. ) = Int32.div
let ( ~-. ) = Int32.neg
end
module Int64_as_float =
struct
let ( +. ) = Int64.add
let ( -. ) = Int64.sub
let ( *. ) = Int64.mul
let ( /. ) = Int64.div
let ( ~-. ) = Int64.neg
end
module Int_as_int_overflow =
(* from http://alan.petitepomme.net/cwn/2004.06.22.html *)
struct
exception Overflow
let ( + ) a b =
let c = a + b in
if (a lxor b) lor (a lxor (lnot c)) < 0 then c else raise Overflow
let ( - ) a b =
let c = a - b in
if (a lxor (lnot b)) lor (b lxor c) < 0 then c else raise Overflow
let ( * ) a b =
let c = a * b in
if Int64.of_int c = Int64.mul (Int64.of_int a) (Int64.of_int b)
then c else raise Overflow
let ( / ) a b =
if a = min_int && b = -1 then raise Overflow else a / b
let ( ~- ) x =
if x <> min_int then -x else raise Overflow
end