-
Notifications
You must be signed in to change notification settings - Fork 19
/
Copy pathdeveloping_application_with_ocaml.tex
750 lines (626 loc) · 19.9 KB
/
developing_application_with_ocaml.tex
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
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
\subsection{Developing Applications with Objective Caml}
\begin{enumerate}
\item caveat
\begin{enumerate}
\item + (modulo the boundary, \emph{will not be checked})
\item $1.0/0.0 \rightarrow \infty $
\item $+. -. *. /. **$ mod ceil floor sqrt exp log log10 cos sin tan acos asin atan
\item $asin 3.14 \rightarrow nan $
\item \verb|char_of_int 255| $\rightarrow$ \verb|'\255'| (can not display)
\item \verb|char_of_int int_of_char string_of_int int_of_string|
\verb|string_of_int 2551 -> ``2551''|
\item string (length $\le 2^{24} - 6$ )
\item == (\textit{physical equal}) (=, != <>)
\begin{alternate}
true == true;;
- : bool = true
# 3 == 3;;
- : bool = true
# 1. == 1.;;
- : bool = false
\end{alternate}
\item int * int * int is different from (int * int ) * int
\item unreasonable parametric equality \verb|(=) : 'a -> 'a -> bool|
\item recursive declaration
\begin{ocamlcode}
let rec ones = 1 :: ones;;
\end{ocamlcode}
\begin{ocamlcode}
val ones : int list =
[1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1;
1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1;
1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1;
1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1;
1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1;
1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1;
1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1;
1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1;
1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1;
1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1;
1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1;
1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1;
...]
\end{ocamlcode}
\begin{ocamlcode}
let special_size l =
let rec size_aux prev = function
|[] -> 0
|_ :: l1 -> if List.memq l1 prev then 1 else 1 + size_aux (l1::prev) l1 in size_aux [l] l;;
\end{ocamlcode}
\begin{ocamlcode}
val special_size : 'a list -> int = <fun>
\end{ocamlcode}
\begin{alternate}
# special_size ones;;
- : int = 1
# let rec twos = 1 :: 2 :: twos in special_size twos;;
- : int = 2
# special_size [];;
- : int = 0
\end{alternate}
\item combine patterns \\
p1 | .. | pn (all name is forbidden within these patterns)
'a' .. 'e'
\begin{alternate}
let test 'a' .. 'e' = true;;
^^^^^^^^^^^^^^^^^
\end{alternate}
\begin{ocamlcode}
Warning 8: this pattern-matching is not exhaustive.
Here is an example of a value that is not matched:
'f'
val test : char -> bool = <fun>
\end{ocamlcode}
\item records
\begin{alternate}
type complex = {re:float;img:float};;
type complex = { re : float; img : float; }
# let add {re; img} {re; img} = 3;;
val add : complex -> complex -> int = <fun>
# let add {re; img} {re; img} = {re = re +. re; img = img +. img};;
val add : complex -> complex -> complex = <fun>
\end{alternate}
\item \emph{redefinition marsks the previous one, while values of the masked types
still exist, but it now turns to be an abstract type }
\item exception
\begin{enumerate}
\item \verb|Match_failure Division_by_zero Failure|
\item exception Name of t -- monomorphic , extensible sum Type \\
when pattern match your exception, its type should be fixed
\item control flow
\end{enumerate}
\item {\bf disagree over interface} \\
when toplevel loads the same module (only the name is the same),
it will check the interface is equal, this sucks since ocaml has
flat namespace for module
\end{enumerate}
\item sharing \\
for structured values, it will be sharing , however,
\emph{vectors of floats don't share}
\begin{alternate}
let a = Array.create 3 0.;;
val a : float array = [|0.; 0.; 0.|]
# a.(0)==a.(1);;
- : bool = false
\end{alternate}
\item weak type variables \\
\begin{alternate}
let b = ref []
(* b should '_a list ref, since b is not pure, cannot be shared *)
let a = []
(* a : 'a list *)
let a = None
(* a : 'a option *)n
let a = Array.create 3 None
(* '_a option array *)
# type ('a,'b) t ={ch1 : 'a list; mutable ch2 : 'b list};;
type ('a, 'b) t = { ch1 : 'a list; mutable ch2 : 'b list; }
# let v = {ch1=[];ch2=[]};;
val v : ('a, '_b) t = {ch1 = []; ch2 = []}
\end{alternate}
\textit{mutable sharing conflicts with polymorphism}
\item library
\begin{enumerate}
\item List \\
\begin{ocamlcode}
@ length hd tl nth rev append rev_append concat flatten
iter map rev_map left_fold fold_right iter2 map2 rev_map2
fold_left2 fold_right2 for_all exists for_all2 exists2
mem memq find filter partition assoc assq remove_assoc remove_assq
split combine sort statble_sort fast_sort merge
\end{ocamlcode}
\begin{alternate}
# List.assq 3 [3,4;1,2];;
- : int = 4
# List.assq 3. [3.,4;1.,2];;
Exception: Not_found.
\end{alternate}
\item Array \\
\verb|Array.create_matrix creates Non-Rectangular matrices|
\begin{ocamlcode}
length get set make create init -- when you don't want to initialize
make_matrix (int->int->'a -> 'a array array) create_matrix;
append concat sub copy fill ('a array -> int -> int -> 'a -> int)
blit (Array.Labels.blit), to_list, of_list map iteri mapi fold_left
fold_right sort stable_sort fast_sort unsafe_get unsafe_set copy
\end{ocamlcode}
\item IO \\
\begin{ocamlcode}
open_in open_out close_in close_out input_line
input : Batteries.Legacy.in_channel -> string -> int -> int -> int = <fun>
output: Batteries.Legacy.out_channel -> string -> int -> int -> unit =<fun>
read_line print_string print_newline print_endline
\end{ocamlcode}
\item stack (imperative data structure actually)
\begin{ocamlcode}
exceptin Empty
create
type 'a t = { mutable c : 'a list }
(* mutable to delay initialization *)
push pop top clear copy is_empty length iter enum copy
of_enum print
module Exceptionless
top : 'a t -> 'a option, pop
\end{ocamlcode}
\item stream \textbf{imperative}
\begin{ocamlcode}
'a t
exception Failure
exception Error of string
from
of_list of_string of_channel iter empty peek junk count npeek
iapp icons ising lapp lcons lsing
sempty slazy dump npeek
\end{ocamlcode}
syntax extension (for my experience, use it in shell, but not in
tuareg toplevel)
\begin{ocamlcode}
let concat_stream a b = [<a;b>]
\end{ocamlcode}
\begin{ocamlcode}
val concat_stream :
'a Batteries.Stream.t -> 'a Batteries.Stream.t -> 'a Batteries.Stream.t =
\end{ocamlcode}
expression not preceded by an \` considered to be sub-stream
destructive pattern matching (camlp5 or extended parser can merge)
consumed (error), failure
\item Array List String Hashtbl Buffer Queue
\item Sort
\begin{ocamlcode}
module X = Sort ;;
\end{ocamlcode}
\begin{ocamlcode}
module X :
sig
val list : ('a -> 'a -> bool) -> 'a list -> 'a list
val array : ('a -> 'a -> bool) -> 'a array -> unit
val merge : ('a -> 'a -> bool) -> 'a list -> 'a list -> 'a list
end
\end{ocamlcode}
\item Weak (vector of weak pointers) abstract type
\begin{ocamlcode}
sig
type 'a t = 'a Weak.t
end
\end{ocamlcode}
\item Printf
\begin{ocamlcode}
%t -> (output->unit)
%t%s -> (output->unit)->string->unit
\end{ocamlcode}
they all should be processed at \textbf{compile time}
\item Digest \\
hash functions return a fingerprint of their entry (reversible)
\begin{ocamlcode}
val string : string -> t -- fingerprint of a string
val file : string -> t -- fingerprint of a file
\end{ocamlcode}
\item Marshal estimate data size
\begin{alternate}
type external_flag = No_sharing | Closures
let size x = x |> flip Marshal.to_string [] |> flip Marshal.data_size 0;; ;;
val size : 'a -> int = <fun>
# size 3;;
- : int = 1
# size 3.;;
- : int = 9
# size "ghsogho";;
- : int = 8
# size "ghsogho1";;
- : int = 9
# size "ghsogho1ah";;
- : int = 11
# size 111;;
- : int = 2
\end{alternate}
\item Sys
\begin{ocamlcode}
os_type interactive word_size max_string_length
max_array_length time argv getenv command file_exists
remove rename chdir getcwd
\end{ocamlcode}
\begin{alternate}
# float (Sys.max_string_length ) /. (2. ** 57.);;
- : float = 0.999999999999999889
\end{alternate}
\item Arg Filename Printexc
\item Printexc
\begin{ocamlcode}
# module P = Printexc;;
\end{ocamlcode}
\begin{ocamlcode}
module P :
sig
val to_string : exn -> string
val catch : ('a -> 'b) -> 'a -> 'b
val get_backtrace : unit -> string
val record_backtrace : bool -> unit
val backtrace_status : unit -> bool
val register_printer : (exn -> string option) -> unit
val pass : ('a -> 'b) -> 'a -> 'b
val print : 'a BatInnerIO.output -> exn -> unit
val print_backtrace : 'a BatInnerIO.output -> unit
end
\end{ocamlcode}
\item Num
\item \verb|Arith_status|
\begin{ocamlcode}
# module X = Arith_status;;
\end{ocamlcode}
\begin{ocamlcode}
module X :
sig
val arith_status : unit -> unit
val get_error_when_null_denominator : unit -> bool
val set_error_when_null_denominator : bool -> unit
val get_normalize_ratio : unit -> bool
val set_normalize_ratio : bool -> unit
val get_normalize_ratio_when_printing : unit -> bool
val set_normalize_ratio_when_printing : bool -> unit
val get_approx_printing : unit -> bool
val set_approx_printing : bool -> unit
val get_floating_precision : unit -> int
val set_floating_precision : int -> unit
end
\end{ocamlcode}
\item Dynlink \\
choice at execution time, load a new module and hide the
code code (hot-patch)
actually (\#load is kinda hot-patch), however to write it in programs
\emph{more flexible} than \#load , load requires its name are fixed, and
load will check .mli file, Dynlink \textbf{does not} do this check, while when you
want to do X.blabla, it still checks, so still don't work, only side
effects will work.
\begin{ocamlcode}
#direcotry "+dynlink";;
#load "dynlink.cma";;
Dynlink.loadfile "test.cmo";;
\end{ocamlcode}
\end{enumerate}
\item syntaxes
\item expr
\begin{ocamlcode}
exp ::=value-path -- value-name or module-path.value-name
| constant
| ( expr )
| begin expr end
| ( expr : typexpr )
| expr , expr { , expr } -- tuple
| constr expr -- constructor
| `tag-name expr -- polymorphic variant
| expr :: expr -- list
| [ expr { ; expr } ]
| [| expr { ; expr } |]
| { field = expr { ; field = expr } }
| { expr with field = expr { ; field = expr } }
| expr { argument }+ -- application
| prefix-symbol expr -- prefix operator
| expr infix-op expr
| expr . field
| expr . field <- expr -- still an expression
| expr .( expr )
| expr .( expr ) <- expr
| expr .[ expr ]
| expr .[ expr ] <- expr
| if expr then expr [ else expr ]
| while expr do expr done
| for ident = expr ( to | downto ) expr do expr done
| expr ; expr
| match expr with pattern-matching
| function pattern-matching
| fun multiple-matching -- multiple parameters matching
| try expr with pattern-matching
| let [rec] let-binding { and let-binding } in expr
| new class-path
| object class-body end
| expr # method-name
| inst-var-name
| inst-var-name <- expr
| ( expr :> typexpr )
| ( expr : typexpr :> typexpr )
| {< inst-var-name = expr { ; inst-var-name = expr } >}
| assert expr
| lazy expr
argument::=expr
| ~ label-name
| ~ label-name : expr
| ? label-name
| ? label-name : expr
pattern-matching::=
[|] pattern [when expr]-> expr { |pattern [when expr] -> expr }
multiple-matching::= { parameter }+ [when expr]-> expr
let-binding::=pattern = expr
| value-name { parameter } [: typexpr] = expr
parameter::=pattern
| ~ label-name
| ~ ( label-name [: typexpr] )
| ~ label-name : pattern
| ? label-name
| ? ( label-name [: typexpr] [= expr] )
| ? label-name : pattern
| ? label-name : ( pattern [: typexpr] [= expr] )
\end{ocamlcode}
\begin{alternate}
let f ?test:(Some x ) y = x + y;;
^^^^^^^^^^^^^^^^^^^^^^^^^
\end{alternate}
\begin{ocamlcode}
Warning 8: this pattern-matching is not exhaustive.
Here is an example of a value that is not matched:
None
val f : ?test:int -> int -> int = <fun>
\end{ocamlcode}
\item pattern
\begin{ocamlcode}
pattern ::= value-name
| _
| constant
| pattern as value-name
| ( pattern )
| ( pattern : typexpr )
| pattern | pattern
| constr pattern
| `tag-name pattern
| #typeconstr-name -- object ?
| pattern { , pattern }
| { field = pattern { ; field = pattern } }
| [ pattern { ; pattern } ]
| pattern :: pattern
| [| pattern { ; pattern } |]
| lazy pattern
\end{ocamlcode}
\item toplevel-phrase
\begin{ocamlcode}
toplevel-input::= { toplevel-phrase } ;;
toplevel-phrase::=definition
| expr
| #ident directive-argument
directive-argument::=epsilon
| string-literal
| integer-literal
| value-path
defition ::= let [rec] let-binding {and let-binding}
| external value-name : typexpr = external-declartion
| type-definition
| exception-defition
| class-definition
| classtype-definition
| module module-name {(module-name : module-type)} [:module-type] = module-expr
| module type module-name = module-type
| open module-path
| include module-expr
\end{ocamlcode}
\item type-definition
\begin{ocamlcode}
type-definition ::= type typedef { and typedef }
typedef ::= [type-params] typeconstr-name [type-information]
type-information::=
[type-equation] [type-representation]{ type-constraint }
type-equation::= = typexpr
type-representation::=
= constr-decl { | constr-decl }
| = { field-decl { ; field-decl } }
type-params::= type-param
| ( type-param { , type-param } )
type-param::= ' ident
| + ' ident
| - ' ident
constr-decl::= constr-name
| constr-name of typexpr { * typexpr }
field-decl::= field-name : poly-typexpr
| mutable field-name : poly-typexpr
type-constraint ::=constraint ' ident = typexpr
\end{ocamlcode}
\begin{alternate}
# type t;;
type t
\end{alternate}
\item interoperating with C
Difficutilies
\begin{enumerate}
\item Machine reperesentation of data
\item GC \\
calling a c function from ocaml must not modify the memory in ways incompatible
with ocaml gc.
\item Exceptions \\
C does not support exceptions, different mechanisms for aborting computations,
this complicates ocaml's exception handling
\item sharing common resources \\
input-output. each language maintains its own input-output buffers.
\end{enumerate}
Communications
\begin{enumerate}
\item external declarations \\
it associates a c function definition with an ocaml name, while giving the
type of the latter.
\begin{bluetext}
external caml_name : type = "C_name"
val caml_name : type
\end{bluetext}
both workds, but in the latter case, calls to the c function \textit{first go}
through the general function application mechanism of ocaml. This is slightly
less efficient, but hides the implementation of the function as a c function.
\item external functions with more than five arguments
\begin{bluetext}
external caml_name : type = "C_name_bytecode" "C_name_native"
\end{bluetext}
\end{enumerate}
\end{enumerate}
\subsubsection{chap7 Development Tools}
\label{sec:chap7-devel-tools}
\begin{enumerate}
\item Command names \\
\item chap10 Program Analysis Tool \\
\begin{enumerate}
\item ocamldep \\
\begin{tabular}{|c|c|}
-I & add dir \\
-impl,-intf & \\
-ml(i)-synonym <e> & cosider <e> as a synonym of .ml(i) extension \\
-modules & Print module dependencies in raw form(not suitable for make) \\
-native & generate dependencies for a pure native-code project \\
-slash & for windows \& unix \\
\end{tabular}
\begin{ocamlcode}
ocamldep -modules *.ml
\end{ocamlcode}
\begin{ocamlcode}
ta.ml: Array Printf
tb.ml: Array Ta
\end{ocamlcode}
\begin{ocamlcode}
ocamldep *.ml
\end{ocamlcode}
\begin{ocamlcode}
ta.cmo:
ta.cmx:
tb.cmo: ta.cmo
tb.cmx: ta.cmx
\end{ocamlcode}
other examples
\begin{bluetext}
ocamlfind ocamldep -modules dir_top_level_util.ml > dir_top_level_util.ml.depends
ocamlfind ocamldep -pp 'camlp4of -parser pa_mikmatch_pcre.cma' -modules dir_top_level.ml > dir_top_level.ml.depends
\end{bluetext}
\item debug
\#(un)trace command ,\#untrace\_all.
\begin{alternate}
let verify_div a b q r = a = b * q + r ;;
val verify_div : int -> int -> int -> int -> bool = <fun>
# #trace verif_div ;;
Unbound value verif_div.
# #trace verify_div ;;
verify_div is now traced.
\end{alternate}
\begin{ocamlcode}
verify_div 11 5 2 1 ;;
\end{ocamlcode}
\begin{ocamlcode}
verify_div <-- 11
verify_div --> <fun>
verify_div* <-- 5
verify_div* --> <fun>
verify_div** <-- 2
verify_div** --> <fun>
verify_div*** <-- 1
verify_div*** --> true
- : bool = true
\end{ocamlcode}
\begin{bluetext}
let rec belongs_to (e:int) = function
| [] -> false
| t :: q -> (e=t) || belongs_to e q;;
val belongs_to : int -> int list -> bool = <fun>
# #trace belongs_to;;
belongs_to is now traced.
# belongs_to 4 [3;5;7;4];;
belongs_to <-- 4
belongs_to --> <fun>
belongs_to* <-- [3; 5; 7; 4]
belongs_to <-- 4
belongs_to --> <fun>
belongs_to* <-- [5; 7; 4]
belongs_to <-- 4
belongs_to --> <fun>
belongs_to* <-- [7; 4]
belongs_to <-- 4
belongs_to --> <fun>
belongs_to* <-- [4]
belongs_to* --> true
belongs_to* --> true
belongs_to* --> true
belongs_to* --> true
- : bool = true
\end{bluetext}
\begin{bluetext}
# let rec belongs to (e : int) = function
[] -> false
| t :: q -> belongs to e q || (e = t) ; ;
val belongs_to : int -> int list -> bool = <fun> # #trace belongs to ;;
belongs_to is now traced.
# belongs to 3 [3;5;7] ;;
belongs_to <-- 3
belongs_to --> <fun>
belongs_to* <-- [3; 5; 7]
belongs_to <-- 3
belongs_to --> <fun>
belongs_to* <-- [5; 7]
belongs_to <-- 3
belongs_to --> <fun>
belongs_to* <-- [7]
belongs_to <-- 3
belongs_to --> <fun>
belongs_to* <-- []
belongs_to* --> false
belongs_to* --> false
belongs_to* --> false
belongs_to* --> true
- : bool = true
\end{bluetext}
Trace providing a mechanism for the efficiency analysis of recursive functions, not that friendly, however, no idented output.
To make things worse, trace \textit{does not show the value corresponding to an argument of a parameterized type}. The toploop can show
only monomorphic types.
Moreover, it only keeps the inferred types of
\textit{global declarations}. Therefore after compilation of the
expression, the toplevel in fact \textit{no longer } processes any
furthuer type information about the expression.
Only global type declarations are kept in the environment of the
toplevel loop, \textit{local functions} can not be traced for the same reasons
as above
\begin{bluetext}
let rec belongs_to e = function
| [] -> false
| t :: q -> (e=t) || belongs_to e q;;
val belongs_to : 'a -> 'a list -> bool = <fun>
# belongs_to 4 [3;5;7;4];;
- : bool = true
# #trace belongs_to;;
belongs_to is now traced.
# belongs_to 4 [3;5;7;4];;
belongs_to <-- <poly>
belongs_to --> <fun>
belongs_to* <-- [<poly>; <poly>; <poly>; <poly>]
belongs_to <-- <poly>
belongs_to --> <fun>
belongs_to* <-- [<poly>; <poly>; <poly>]
belongs_to <-- <poly>
belongs_to --> <fun>
belongs_to* <-- [<poly>; <poly>]
belongs_to <-- <poly>
belongs_to --> <fun>
belongs_to* <-- [<poly>]
belongs_to* --> true
belongs_to* --> true
belongs_to* --> true
belongs_to* --> true
- : bool = true
\end{bluetext}
\item ocamldbg
The \textit{-g} option produces a \textit{.cmo} file with the
debugging information. (bytecode only)
\end{enumerate}
\end{enumerate}
%%% Local Variables:
%%% mode: latex
%%% TeX-master: "../master"
%%% End: