This file is indexed.

/usr/lib/mlton/sml/basis/notes.txt is in mlton-basis 20130715-3.

This file is owned by root:root, with mode 0o644.

The actual contents of the file can be viewed below.

   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
 747
 748
 749
 750
 751
 752
 753
 754
 755
 756
 757
 758
 759
 760
 761
 762
 763
 764
 765
 766
 767
 768
 769
 770
 771
 772
 773
 774
 775
 776
 777
 778
 779
 780
 781
 782
 783
 784
 785
 786
 787
 788
 789
 790
 791
 792
 793
 794
 795
 796
 797
 798
 799
 800
 801
 802
 803
 804
 805
 806
 807
 808
 809
 810
 811
 812
 813
 814
 815
 816
 817
 818
 819
 820
 821
 822
 823
 824
 825
 826
 827
 828
 829
 830
 831
 832
 833
 834
 835
 836
 837
 838
 839
 840
 841
 842
 843
 844
 845
 846
 847
 848
 849
 850
 851
 852
 853
 854
 855
 856
 857
 858
 859
 860
 861
 862
 863
 864
 865
 866
 867
 868
 869
 870
 871
 872
 873
 874
 875
 876
 877
 878
 879
 880
 881
 882
 883
 884
 885
 886
 887
 888
 889
 890
 891
 892
 893
 894
 895
 896
 897
 898
 899
 900
 901
 902
 903
 904
 905
 906
 907
 908
 909
 910
 911
 912
 913
 914
 915
 916
 917
 918
 919
 920
 921
 922
 923
 924
 925
 926
 927
 928
 929
 930
 931
 932
 933
 934
 935
 936
 937
 938
 939
 940
 941
 942
 943
 944
 945
 946
 947
 948
 949
 950
 951
 952
 953
 954
 955
 956
 957
 958
 959
 960
 961
 962
 963
 964
 965
 966
 967
 968
 969
 970
 971
 972
 973
 974
 975
 976
 977
 978
 979
 980
 981
 982
 983
 984
 985
 986
 987
 988
 989
 990
 991
 992
 993
 994
 995
 996
 997
 998
 999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
Date: Tue, 23 Jul 2002 11:49:57 -0400 (EDT)
From: Matthew Fluet <fluet@CS.Cornell.EDU>


John and SML implementers,

Here are a loose collection of notes I've taken while starting to
update the MLton implementation of the SML Basis Library to the latest
version.  They span quite a range: errata and typos, signature
constraint concerns, and some design questions.  Thus far, I've looked
at the structures that had been grouped under the headings General,
Text, Integer, Reals, Lists, and Arrays and Vectors (i.e., excluding
IO, System, and Posix) in the "old" web specification.

A few high level comments:

* As an organizational principal, I liked the grouping of modules into
  larger collections used in the "old" web specification better than
  the long alphabetical list.
* I'm quite happy to see opaque signature matches for most structures.
  In particular, I think it will help avoid porting problems between
  implementations that provide different INTEGER structures, especially
  when LargeInt = Int in one implementation and LargeInt = IntInf in 
  another.

Required and optional components, Top-level:

* A number of structures have an opaque signature match in
  overview.html, but not in the corresponding structure specific page:
  General, Bool, Option, List, ListPair, IntInf, 
  Array, ArraySlice, Vector, VectorSlice.
* Word8Array2 is listed as required in overview.html,
  but its signature, MONO_ARRAY2, is not required.
  Furthermore, Word8Array2 is marked optional in mono-array2.html.
  I don't quite see a rationale for Word8Array2 being required.
* With the addition of  val ~ : word -> word  to the WORD signature,
  presumably ~ should be overloaded at num, rather than at intreal.

Reals:

* In pack-float.html, the where type clauses are incorrect:
  structure PackRealBig :> PACK_REAL  
    where type PackRealBig.real = Real.real
  should be
  structure PackRealBig :> PACK_REAL  
    where type real = Real.real
* Likewise, in most places, references to basic types are unqualifed,
  so perhaps the where clause should read
  where type real = real
  for the PackRealBig and PackRealLittle structures.

Arrays and Vectors:

* In vector-slice.html, the description of subslice references |arr|
  when it should reference |sl|.
* In {[mono-]array[-slice],[mono-]vector[-slice]}.html, the
  description of findi references appi when it should reference findi.
* In mono-array-slice.html, structure CharArraySlice has the clause
  where type array = CharVector.vector
  which should be
  where type array = CharArray.array.
* In mono-{vector[-slice],array[-slice],array2}.html, there are
  Word<N> structures but no (default word) Word structures.
* In mono-vector.html, structure CharVector has the clause
  where type elem = Char.char
  while the other monomorphic vectors of basic types reference
  the unqualified type; i.e. structure BoolVector has the clause
  where type elem = bool.
* There are no "See also"'s into MONO_VECTOR_SLICE or MONO_ARRAY_SLICE
  from MONO_VECTOR or MONO_ARRAY.
* A long discussion about types defined in
  [MONO_]{ARRAY,VECTOR}[_SLICE] signatures; deferred to a separate
  email. 

Really nit-picky:

* Ordering of comparison functions (>, >=, etc.) and unary negation
  are different within INTEGER and WORD.
* Ordering of functions in CHAR seems awkward.
* Ordering of full, slice, subslice different in ARRAY_SLICE and
  VECTOR_SLICE. 
* Ordering of foldi/fold and modifi/modify different in ARRAY2 and
  MONO_ARRAY2. 

Top-level and opaque signatures:
* I think it would be useful to see the entire top-level of required
  structures written out with their respective signature constraints.
  For example, in the description of the Math structure, the spec
  reads: "The top-level structure Math provides these functions for
  the default real type Real.real."  Because the top-level Math
  structure has an opaque signature match (in overview.html), then the
  sentence above implies that there ought to be the constraint 
  where type real = real (or Real.real).  
  Granted, none of the other structures in overview.html have where
  clauses, and most type constraints are documented in the structure
  specific pages, but the constraint on the top-level Math.real
  slipped my mind when I first looked at it.

-Matthew

******************************************************************************
******************************************************************************

Date: Tue, 23 Jul 2002 11:54:09 -0400 (EDT)
From: Matthew Fluet <fluet@CS.Cornell.EDU>


As promised, here is a longish look at the types used in Arrays and
Vectors.

Array and Vector design:

* The ARRAY signature includes type 'a vector.
  Presumably, type 'a Array.vector = type 'a Vector.vector, but no
  constraint makes this explicit.
* MONO_ARRAY_SLICE includes type vector and type vector_slice, 
  while the ARRAY_SLICE signature explicitly references 
  'a VectorSlice.slice and 'a Vector.vector.
* VECTOR_SLICE doesn't include 'a vector, but has
  val mapi : (int * 'a -> 'b) -> 'a slice -> 'b vector
  val map  : ('a -> 'b) -> 'a slice -> 'b vector;
  On the other hand, full, slice, base, vector, and concat
  reference 'a Vector.vector.

For consistency, I'd prefer to see
signature VECTOR = 
  sig  type 'a vector  ... end
signature VECTOR_SLICE = 
  sig  type 'a vector  type 'a slice  ... end 
signature ARRAY = 
  sig  type 'a vector  type 'a array  ... end
signature ARRAY_SLICE = 
  sig  type 'a vector  type 'a vector_slice
       tyep 'a array  type 'a slice  ... end
signature MONO_VECTOR = 
  sig  type elem  type vector  ... end
signature MONO_VECTOR_SLICE = 
  sig  type elem  type vector  type slice ... end
signature MONO_ARRAY =
  sig  type elem  type vector  type array  ... end
signature MONO_ARRAY_SLICE =
  sig  type elem  type vector  type vector_slice
       type array  type slice  ... end

structure Vector :> VECTOR
structure VectorSlice :> VECTOR_SLICE 
                         where type 'a vector = 'a Vector.vector
structure Array :> ARRAY 
                   where type 'a vector = 'a Vector.vector
structure ArraySlice :> ARRAY_SLICE 
                        where type 'a vector = 'a Vector
                        where type 'a vector_slice = 'a VectorSlice.slice
                        where type 'a array = 'a Array.array
structure BoolVector :> MONO_VECTOR 
                        where type elem = bool
structure BoolVectorSlice :> MONO_VECTOR_SLICE 
                             where type elem = bool
                             where type vector = BoolVector.vector
structure BoolArray :> MONO_ARRAY 
                       where type elem = bool
                       where type vector = BoolVector.vector
structure BoolArraySlice :> MONO_ARRAY_SLICE 
                            where type elem = bool
                            where type vector = BoolVector.vector
                            where type vector_slice = BoolVectorSlice.slice
                            where type array = BoolArray.array

While semantically, this shouldn't be any different than the
specification, it could effect type-error messages.  For example, if I
have the structure Foo:

structure Foo = struct
   open BoolArraySlice

   val copyVec0 {src: vector_slice, 
                 dst: array} = copyVec {src = src, dst = dst, di = 0}   
end

which I decide to generalize to polymorphic array slices, then just
changing BoolArraySlice to ArraySlice will lead to different
type-error messages: either "ubound type constructor: vector_slice"
(under the specification) or "type constructor vector_slice given 0
arguments, wants 1" (under the signatures given above); and an arity
error for array in either case.  It's not much of an argument, but I
need to replace vector_slice with 'a VectorSlice.slice under the
specification, while I only need to add 'a under the sigs above.


Array2:
* Why not have an ARRAY2_REGION analagous to ARRAY_SLICE?
  Likewise, how about VECTOR2 and VECTOR2_REGION?
  I think the decision to separate Arrays and Vectors from
  their corresponding slices is a nice design choice, and I'd be in
  favor of extending it to multi-dimentional ones.
* Should ARRAY2 have findi/find, exists, all?  collate?

******************************************************************************
******************************************************************************

Date: Thu, 25 Jul 2002 15:20:01 +0200
From: Andreas Rossberg <rossberg@ps.uni-sb.de>


Like Matthew I started implementing the latest version of the Basis spec
for Alice and Hamlet. I'm quite happy with most of the changes. It was a
surprise to discover the presence of a Windows structure, though :-)

Here is my list of comments, some of which may duplicate observations
already made by Matthew. They primarily cover global issues and the
required part of the library, though I haven't looked deeper into the IO
and Posix parts yet. I also included some proposals for modest additions
to the library, which I believe are useful and fit its spirit.


Trivial bugs, typos, cosmetics
------------------------------

* Overview:
  - INT_INF appears in the list of required signatures.
  - WordArray2 appears under the list of required structures,
    instead of optional ones.

* LIST_PAIR:
  - Typo in description of allEq: double "the".

* SUBSTRING:
  - The scan example uses the deprecated "all" function.

* VECTOR_SLICE:
  - Typo in synopsis of subslice: s/opt/sz/.
  - Typo in description of subslice: s/|arr|/|sl|/.
  - Typo in description of findi: s/appi/findi/.
  - Signature sometimes uses Vector.vector instead of plain vector.
  - The equation for mapi can be simplified to:
        Vector.fromList (foldri (fn (i,a,l) => f(i,a)::l) [] slice)

* MONO_VECTOR_SLICE and ARRAY_SLICE and MONO_ARRAY_SLICE:
  - Typo in synopsis of subslice: s/opt/sz/.
  - Typo in description of findi: s/appi/findi/.

* BYTE:
  - Accidental "val" keyword in synopsis of some functions.

* TEXT_IO:
  - The "where" constraints contain erroneously qualified ids.
  - The specification of the TEXT_IO signature is not valid SML'97,
    since StreamIO is specified twice. You might want to add a
    comment regarding that.
  - The constraints for types vector and elem are redundant
    (in fact, invalid), because the signature TEXT_STREAM_IO
    already specifies the necessary equations.

* The use of variable names is sometimes inconsistent:
  - Predicate arguments to higher-order functions are usually
    named "f" (eg. List.all), sometimes "p" (eg. String.tokens,
    StringCvt.splitl), and sometimes even "pred" (eg. ListPair.all).
  - Similarly, fold functions mostly use "init" to name initial
    accumulators, except in the List and ListPair modules.



Ambiguities / Unclear Details
-----------------------------

* Overview:
  - The subsection about dependencies among optional modules has
    disappeared. Does that mean that there aren't any anymore?
    (The nice subsection about design rules and conventions also
    has gone.)

* The intended meaning of opaque signature constraints is not always
  clear to me. Sometimes the prose contains remarks about additional
  equalities that are not appearent from the signature constraints.
  For example, is or isn't
  - Text.Char.char = Char.char ? (and so on for the rest of Text)
  - LargeInt.int = IntN.int (for some structure IntN) ?
    (likewise LargeWord.word, LargeReal.real)
  - Char.string = String.string ?
  - Math.real = Real.real ?
  In particular, the spec sometimes speaks of "equal structures",
  which has no real technical meaning in SML'97.
  Note that from the opaque matching on the overview page one might
  even conclude that General.unit <> {} !

* The type specification of String.string and CharVector.vector
  is circular:
        structure String :> STRING
               where type string = CharVector.vector
        structure CharVector :> MONO_VECTOR
               where type vector = String.string
  Likewise for Substring.substring and CharVectorSlice.slice.
  A respective defining structure should be chosen.

* STRING:
  - Function fromString has a special case that is not covered by
    implementing the function through straight-forward iterative
    application of the Char.scan function, namely a trailing gap
    escape (\f...f\) as in "foo\\ \\" or "foo\\ \\\000" (where \000
    is an non-convertible character). Several implementations I
    tried get that detail wrong, so a corresponding note might be
    in order. Moreover, it is not completely obvious from the
    description what the result should be for strings that contain
    a gap escape as the only convertible sequence, e.g. "\\ \\" or
    "\\ \\\000" - it is supposed to be SOME "", I guess.

* SUBSTRING:
  - Shouldn't span raise Span if i' < i? Otherwise, contrary
    to the prose, it in fact accepts arguments where ss' is
    left to ss, as long as they overlap (which is rather odd).
  - For the curried triml/trimr it is not clear whether an
    Subscript exception has to be raised already if k < 0 but no
    second argument is applied.



Naming and structuring
----------------------

Its nicely chosen regular naming conventions and structure are two of
the aspects I like most about the Standard Basis. The following list
enumerates the few cases where I feel that the spec violates its own
conventions.

* WORD:
  - The fromLargeWord and toLargeWord functions should drop
    the "Word" suffix to be consistent with the corresponding
    functions in the REAL and INTEGER signatures.

* CHAR:
  - The functions contains/notContains should be moved to the
    STRING signature, as they are similar to find/exist
    operations and thus functionality of the aggregate. The
    type string could then be removed from the signature.

* ARRAY_SLICE and MONO_ARRAY_SLICE:
  - The function copyVec seems completely out of place: it does
    neither operate on array slices, nor on vectors. But honestly
    I have got no idea where else to put it :-(

* STRING and SUBSTRING:
  - There is a certain asymmetry between slices and substrings
    which tends to confuse at least myself when hacking. For more
    consistency I propose:
    (1) changing the type of Substring.substring to
        string * int * int option -> substring
        (for consistency with VectorSlice.slice),
    (2) renaming Substring.slice to Substring.subsubstring,
        (for consistency with VectorSlice.subslice),
    (3) removing Substring.{app,foldl,foldr} (there are no similar
        functions in the STRING signature, and in both cases they
        are available through CharVector/CharVectorSlice),
    (4) removing String.extract and Substring.extract (the same
        functionality is available through CharVector[Slice]).
  - I believe the deprecated Substring.all can be removed for good.
    After all, there are more serious incompatible changes being
    made (e.g. array copying functions).

* Vectors and arrays:
  - While the lib consistently uses the to/from convention for
    conversions on basic types, it sometimes uses adhoc conventions
    for aggregates. I propose renaming:
    (1) Array.vector to Array.toVector
    (2) VectorSlice.vector to VectorSlice.toVector,
    (3) ArraySlice.vector to ArraySlice.toVector,
    (4) Substring.string to Substring.toString,
  - Since the copy functions have only 3, mostly distinctly typed
    arguments now, there no longer seems to be a strong reason to
    require passing those by notationally heavy records.

* INT_INF:
  - The presence of bit fiddling operators in that signature is
    something that feels exceptionally ad-hoc. Either they should
    be available for all integer types, or there should be a
    separate WORD_INF, with appropriate conversions, that makes
    these available.

* Toplevel:
  - Now that there is Word.~ (which is good) it seems rather odd
    that the toplevel ~ is not overloaded for words, i.e. does not
    have type num-> num.

* Net functionality:
  - I really like the idea of structuring the library namespace as
    it has been done with the OS and Posix structures. I would
    prefer to see something similar being done for the added
    network functionality. More precisely, I propose
    (1) moving the structures Socket, INetSock, GenericSock, and
        the three Net*DB structures into a new wrapper structure
        Net (renaming Net*DB to *DB),
    (2) defining a corresponding signature NET,
    (3) renaming the signatures SOCKET, GENERIC_SOCK and INET_SOCK
        to NET_SOCKET, NET_GENERIC_SOCK and NET_INET_SOCK, resp.,
    (4) moving UnixSock to the Unix structure (renamed as Socket).



Misc. proposals for additional functionality
--------------------------------------------

Here is a small collection of miscellaneous simple functions which I
believe the library is still lacking, either because they are commonly
useful or because they would make the library more regular.

* LIST and LIST_PAIR:
  - The IMHO single most convenient extension to the library would
    be indexed morphisms on lists, i.e. adding
        val appi : (int * 'a -> unit) -> 'a list -> unit
        val mapi : (int * 'a -> 'b) -> 'a list -> 'b list
        val foldli : (int * 'a * 'b -> 'b) -> 'b -> 'a list -> 'b
        val foldri : (int * 'a * 'b -> 'b) -> 'b -> 'a list -> 'b
        val findi : (int * 'a -> bool) -> 'a list -> (int * 'a) option
  - Likewise for LIST_PAIR.
  - LIST_PAIR does not support partial mapping:
        val mapPartial : ('a * 'b -> 'c option) ->
                                'a list * 'b list -> 'c list

* LIST, VECTOR, ARRAY, etc.:
  - Another function on lists that would be very useful from my
    perspective is
        val appr : ('a -> unit) -> 'a list -> unit
    and its indexed sibling
        val appri : (int * 'a -> unit) -> 'a list -> unit
    which traverse the list from right to left.
  - Likewise for all aggregate types.
  - All aggregates come with a fromList function. I often feel the
    need to have inverse toList functions. Use of foldr is obfuscating.

* OPTION:
  - Often using isSome is a bit clumsy. I thus propose adding the dual
        val isNone : 'a option -> bool

* STRING and SUBSTRING:
  - For historical reasons we have {String,Substring}.size instead
    of *.length, which is inconsistent with all other aggregates and
    frequently lets me mix them up when I use them side by side.
    I propose adding aliases
        String.maxLen
        String.length
        Substring.length

* WideChar and WideString:
  - There is no convenient way to convert between the standard and
    wide character set. Would it be reasonable to introduce LargeChar
    and LargeString structures (and so on) and have the CHAR and
    STRING signatures enriched by fromLarge/toLarge functions, as for
    numbers? That would also allow a program to select the widest
    character set available (which is currently impossible within the
    language).

* String conversion:
  - I don't quite see the rationale for which signatures contain a
    scan function and which don't. I believe it makes sense to have
    scan in every signature that has fromString.
  - There should be a function
        val scanC : (Char.char, 'a) StringCvt.reader
                        -> (char, 'a) StringCvt.reader
    to scan strings as C characters. This would make Char.fromCString
    and particularly String.fromCString more modular.
  - How about a dual writer abstraction as with
        type ('a,'b) writer = 'a * 'b -> 'b option
    and supporting fmt functions for basic types? Such a thing might
    be useful for writing to streams or buffers.

* Vectors:
  For some time now I have been trying to use vectors more often
  instead of an often inappropriate list representation. This is
  sometimes made more difficult simply because the library support
  isn't as good as for lists. It improved in the updated version
  but still I miss:
  - Array.fromVector,
  - Vector.mapPartial,
  - Vector.rev,
  - Vector.append (though I guess concat is good enough),
  - most of all: a VectorPair structure.

* Hash functions:
  - Giving every basic type a (default) hash function in addition to
    comparison would be quite useful in conjunction with container
    libraries.

* There is no defining structure for references. I would like to see
        signature REF
        structure Ref : REF
  where REF contains:
        datatype ref = datatype ref
        val ! : 'a ref -> 'a
        val := : 'a ref * 'a -> unit
        val swap : 'a ref * 'a ref -> unit      (* or :=: ? *)
        val map : ('a -> 'a) -> 'a ref -> 'a ref
  You might then consider removing ! and := from GENERAL.

* Signature conventions:
  Some additional conventions would make use of Basis types as
  functor arguments more convenient:
  - Each signature defining an abstract type should make that
    type available under the alias "t" as well (this includes
    monomorphic types as well as polymorphic ones).
  - Every equality type should come with an explicit equality
    function
        val eq : t * t -> bool
    to move away from the reliance on eqtypes.
  - There should be a uniform name for canonical constructor
    functions, e.g. "new" (or at least an alias).

-- 
Andreas Rossberg, rossberg@ps.uni-sb.de

******************************************************************************
******************************************************************************

Date: Fri, 2 Aug 2002 14:04:16 +0100
From: David Matthews <David.Matthews@deanvillage.com>


I've been having another look at the Basis library implementation in 
Poly/ML and in particular the I/O library.  I'm still not sure I fully 
understand the implications of the Stream IO (functional IO) layer and 
in particular the way "canInput" works and interacts with "input".

The definition says that canInput(f, n) returns SOME k "if a call to 
input would return immediately with at least k characters".  
Specifically it does not say "if a call to inputN(f, k) would return 
immediately".   Secondly it says that it "should attempt to return as 
large a k as possible" and gives the example of a buffer containing 10 
characters with the user calling canInput(f, 15).  This suggests that a 
call to canInput could have the effect of committing the stream since a 
perfectly good implementation of "input" would be to return what was 
left of the buffer, i.e. 10 characters, and only read  from the 
underlying stream on a subsequent call to "input".  Yet after a call to 
canInput(f, 15) which returns SOME 15 the call to "input" is forced to 
return at least 15.  In other words a call to canInput changes the 
behaviour of a subsequent call to "input".  Generally, what is the 
behaviour of canInput with an argument larger than the buffer size?  How 
far ahead is canInput expected to read?

A few other notes of things I've discovered, some of which are trivial:

The signature for TextIO.StreamIO contains duplicates of
  where type StreamIO.reader = TextPrimIO.reader
  where type StreamIO.writer = TextPrimIO.writer

There are declared constants for platformWin32Windows2000 and 
platformWin32WindowsXP in the Windows structure.  When I proposed the 
Windows.Config structure I didn't include constants for these versions 
of the OS because the underlying GetVersionEx function returns the same 
value, VER_PLATFORM_WIN32_NT in the dwPlatformId field for NT, Windows 
2000 and XP   It is possible to distinguish these but only using the 
major and minor version fields.  Windows CE does give a different value 
for the platformID.  I would say it is confusing to have these here 
because it implies that it's possible to discriminate on the basis of 
the platformID field.

The example definition of input1 at the bottom of STREAM_IO returns a 
value of type elem option * instream when the signature says it should 
be (elem * instream) option.

Description of "input" function in STREAM_IO signature.  The word "ay" 
should be "may".

--
David.

******************************************************************************
******************************************************************************

Date: Fri, 11 Oct 2002 17:46:59 -0400 (EDT)
From: Matthew Fluet <fluet@CS.Cornell.EDU>


Following up my previous post, here is another loose collection of
notes I've taken while updating the MLton implementation of the SML
Basis Library.  This includes the structures that had been grouped
under the headings System, Posix, and IO in the "old" web
specification.

Required and optional components:
* The optional functors PrimIO, StreamIO, and ImperativeIO are not
  listed among the optional components in overview.html.

Lists:
* The discussion for the ListPair structure says:
  "Note that a function requiring equal length arguments may determine
  this lazily, i.e. , it may act as though the lists have equal length
  and invoke the user-supplied function argument, but raise the
  exception when it arrives at the end of one list before the end of the
  other."
  Such an implementation choice seems to go against the spirit that
  programs run under conforming implementations of the Basis Library
  should behave the same.

Posix:
* In posix.html, last sentence in Discussion: "onsult" instead of
  "consult"
PosixSignal:
* In posix-signal.html, in Discussion: "The name of the coressponding
  ..." sentence is repeated.
PosixError:
* In the discussion of POSIX_ERROR:
  "The name of a corresponding POSIX error can be derived by
  capitalizing all letters and adding the character ``E'' as a
  prefix. For example, the POSIX error associated with nodev is
  ENODEV. The only exception to this rule is the error toobig, whose
  associated POSIX error is E2BIG."
  It isn't clear if this is the intended semantics for errorName and
  syserror.

Time:
* The type time now includes "negative values moving to the past."
  In the absence of negative values, the text for the the
  to{Seconds,Milliseconds,Microseconds} functions to drop fractions of
  the time unit was unambigous.  With negative values, I would
  interpret this as rounding towards zero.  Is this correct?  Would it
  be clearer to describe the rounding as such?
* The + and - functions are required to raise Overflow, although most
  other "result not representable as a time value" error raises Time.
* The - function is written prefix instead of infix in the
  description.
* The scan and fromString functions do not specify how to treat a
  value with greater precision than the internal representation;
  should it have rounding or truncation semantics?  Also, the
  functions are required to raise Overflow for an unrepresentable
  time value.

IO:
* The nice introduction to IO that appears at
  http://cm.bell-labs.com/cm/cs/what/smlnj/doc/basis/pages/io-explain.html
  doesn't seem to be included with the new pages.
* The functor arguments in PrimIO, StreamIO, and ImperativIO functors
  don't match; some use structure A: MONO_ARRAY and others use
  structure Array: MONO_ARRAY.

PrimIO() and PRIM_IO
* The PRIM_IO signature requires pos to be an eqtype, but the PrimIO
  functor argument only requires pos to be a type.
* readArr[NB], write{Vec,Arr}[NB] take "slices" (records of type {buf:
  {vector,array}, i: int, sz: int option}) but no description of the
  appropriate action to take when the slices are invalid.  Presumably,
  they should raise Subscript.
* There are a number of "contradictory" statments:
  "Readers and writers should not, in general, raise the IO.Io
  exception. It is assumed that the higher levels will appropriately
  handle these exceptions."
  "A reader is required to raise IO.Io if any of its functions, except
  close or getPos, is invoked after a call to close. A writer is
  required to raise IO.Io if any of its functions, except close, is
  invoked after a call to close."
  "closes the reader and frees operating system resources. Further
  operations on the reader (besides close and getPos) raise
  IO.ClosedStream."
  "closes the writer and frees operating system resources. Further
  operations (other than close) raise IO.ClosedStream."
* The augment_reader and augment_writer functions may introduce new
  functions.  Should the synthesized operations handle IO.Io
  exceptions and change the function field?  Maybe this falls under
  the "intentionally unspecified" clause.

StreamIO() and STREAM_IO:
* What is the difference between a terminated output stream and a
  closed output stream?  Some operations say what to do when the
  stream is terminated or closed, but many are unspecified when the
  other condition holds.  I resolved this by looking at the IO
  introduction mentioned above, where it discusses stream states.
  But, closeOut is still confusing: "flushes f's buffers, marks the
  stream closed, and closes the underlying writer. This operation has
  no effect if f is already closed. If f is terminated, it should
  close the underlying writer."  Shouldn't closeOut always execute the
  underlying writer's close function?  The only way to terminate an
  outstream is to getOutstream, but I would really expect
  TextIO.closeOut to "really" close the underlying
  file/outstream/writer.
* The IO structure has dropped the TerminatedStream exception, but
  there seem to be sufficient cases when a stream should raise an
  exception when it is terminated.
* The semantics of the vector returned by getReader are unclear.  At
  the very least, the source code for SML/NJ and PolyML have very
  different interpretations, and I've chosen yet another.  I think
  part of the problem is that the word "[un]consumed" only appears in
  the description of this function, so it's unclear what corresponds
  to consumed input.
* I suspect the example under endOfStream is wrong:

  In these cases the StreamIO.instream will also have multiple EOF's;
  that is, it can be that

  val true = endOfStream(f)
  val ("",f') = input f
  val true = endOfStream(f')
  val ("xyz",f'') = input f

  The fact that input f can return two different values would seem to
  violate the principal argument for functional streams!  Looking at
  the aforementioned IO introduction in the "old" pages, I see the
  more reasonable example:

  Consequently, the following is not guaranteed to be true:

  let val z = TextIO.StreamIO.endOfStream f
      val (a,f') = TextIO.StreamIO.input f
      val x = TextIO.StreamIO.endOfStream f'
  in x=z   (* not necessarily true! *)
  end

  whereas the following is guaranteed to be true:

  let val z = TextIO.StreamIO.endOfStream f
      val (a,f') = TextIO.StreamIO.input f
      val x = TextIO.StreamIO.endOfStream f (* note, no prime! *)
  in x=z   (* guaranteed true! *)
  end
* David Matthews's post on Aug. 2 raised questions about canInput
  which are unresolved.

General comments:
* Various operations in IO take "slices", but aren't expressed in
  terms of {Vector,Array}Slice structures.  One difficulty with this
  is that the slice types are not in scope within the IO signatures.  

  I would really advocate making the VectorSlice structure a
  substructure of the Vector structure (and likewise for arrays).
  Even if this isn't done for the polymorphic vector/array structures,
  it would be extremely beneficial for the monomorphic structures,
  where in the {Prim,Stream,Imperative}IO functors, it is impossible
  to access the corresponding monomorphic vector/array slice
  structures.  I found myself using Vector.tabulate when I really
  wanted ArraySlice.vector.

  The "old" MONO_ARRAY signature included structure Vector:
  MONO_VECTOR which gave access to the corresponding monomorphic
  vectors.

-Matthew

******************************************************************************
******************************************************************************

Date: Fri, 13 Dec 2002 15:57:55 +0100
From: Andreas Rossberg <rossberg@ps.uni-sb.de>


Here is a collection of issues and comments we gathered when
implementing the I/O stack from the Standard Basis (primitive, stream,
imperative I/O) for Alice. While in general the specification seems to
be pretty precise and complete, we sometimes found it hard to understand
the semantic details of stream I/O, especially since many of them can
only be derived indirectly from the examples in the discussion section
and there appear to be some minor ambiguities and inconsistencies. Also,
the PrimIO and StreamIO functors cannot always be implemented as
suggested, because of their parametricity in types such as position and
element.

As a general note, the I/O interface does not seem to have been designed
with concurrency in mind. In particular, augmenting readers and writers
cannot be made thread-safe, AFAWCS. This is a bit of a problem for us,
since Alice is relying on concurrency. However, that does not seem to be
an issue easily solved.

        - Leif Kornstaedt, Andreas Rossberg


The IO structure
----------------

* exception Io:

  - function field: (pedantic) The wording seems to imply that only
    functions from STREAM_IO raise the Io exception, but this is
    clearly not the case (consider TextIO.openIn to name just one).

* datatype buffer_mode:

  - There is no specification of what precisely line buffering is
    supposed to mean, in particular for non-text streams.



The PRIM_IO signature
---------------------

* Synopsis:

  - (pedantic) It says that "higher level I/O facilities do not
    access the OS structure directly...". That's somewhat misleading
    since OS does not provide the same functionality anyway (if any,
    it was the Posix structure).

* type reader:

  - Unlike for writers, it is not specified what the minimal set of
    operations is that a reader must support.

  - It is not specified whether multiple end-of-streams may occur.
    Since they are anticipated for StreamIO, one should expect them
    to be possible for underlying readers as well. However, this
    requires clarification of the semantics of several operations.

  - readArr, readArrNB: It is specified nowhere what the option for
    sz is supposed to mean, i.e. what the semantics of NONE is
    (presumably as for slices).

  - readVec, readVecNB: Unlike all other similar read and write
    functions, these two do not accept an option for the size
    argument.

  - avail: The description suggests that the function can be used as
    a hint by inputAll. However, this information is too inaccurate
    to be useful, since (apart from translation issues) the physical
    size of elements cannot be obtained (in particular in the
    StreamIO functor, which is parametric in the element type). In
    practice, endPos seems to be more useful for this purpose. So it
    is not clear what purpose avail could actually serve at all at
    the abstraction level provided by readers.

  - endPos:
    (1) May it block? For example, when reading from terminal or
    from another kind of stream, this can be naturally expected.

    (2) Which position is returned if there are multiple
    end-of-streams?

  - getPos, setPos, endPos, verifyPos: Description should start with
    "when present".

  - setPos, endPos: Should not raise an exception if unimplemented,
    but rather be NONE. Actually, the implementation notes on writers
    state that endPos *must* be implemented for readers.

  - Implementation note, item 6: Why is it likely that the client
    uses getPos frequently? And why should the reader count
    *untranslated* elements (and how would there be actual elements
    before translation)?
    (See also comments on STREAM_IO.filePosIn)

* type writer:

  - writeVec, writeArr, writeVecNB, writeArrNB:
    (1) Again, it is not specified what the optional size means.

    (2) When may k < sz occur without having IO failure? If it is
    arbitrary, then there appears to be no correct way to write a
    sequence of elements, because it is neither possible to detect
    partial element writes (which are explained in the paragraph
    before the Implementation Notes), nor to complete such writes.
    This particularly implies that the StreamIO functor cannot
    implement flushing correctly (see below).

  - getPos, setPos, endPos, verifyPos: Description should start with
    "when present".

  - getPos, setPos: Should not raise an exception if unimplemented,
    but rather be NONE.

  - last paragraph before Implementation Note: Typo, double "plus".

  - first sentence in Implementation Note: (pedantic) Why is this
    put into the implementation notes when it actually seems to be a
    requirement of the specification?

  - last paragraph of Implementation Note:
    (1) States that readers must implement getPos, which seems to be
    contradicted by its optional type.

    (2) Typo, double "need".

* openVector:

  - Is this supposed to support random access? Note that for types
    generated with the PrimIO functor it cannot (see below)! That
    seems to make this function rather useless.

* augmentReader, augmentWriter:

  - It is not possible to synthesize operations in a way that is
    thread-safe in concurrent systems, hence it should be noted that
    augmenting is potentially dangerous.

* There is no reference to the PrimIO functor.



The PrimIO functor
------------------

* General problems:

  - Since the implementation is necessarily parametric in the pos
    type, openVector, nullRd, nullWr cannot create readers that
    allow random access, although one would expect that at least for
    openVector.

* Functor argument:

  - Structure names A and V are inconsistent with the StreamIO and
    ImperativeIO functors.

  - Type pos has to be an eqtype to match the result signature.

  - Since the extract and copy functions have been removed/changed
    from ARRAY and VECTOR signatures, the PrimIO functor now
    naturally requires slice structures for efficient
    implementation. (Likewise the StreamIO functor)

* Functor result:

  - Type sharing of the pos type is not specified, though essential
    for this functor being useful at all.




The STREAM_IO signature
-----------------------

* Synopsis:

  - An exception likely to be raised in by the underlying
    reader/writer is Size, which is not mentioned. OTOH, Fail can
    only occur in the rare case of user-supplied readers/writers, as
    the Basis itself is supposed to never raise it.

* type out_pos:

  - A note on the meaning of this type would be desirable, since its
    canonical representation is (outstream * pos) rather than pos.
    (That also may have caused confusion in the discussion of
    imperative I/O, see below.)

* input1:

  - The signature of this function is inconsistent with all other
    input functions. It should rather have type

        instream -> elem option * instream

    which in fact appears to be the type assumed in the discussion
    example relating input1 to inputN.

* input:

  - Typo, s/ay/may/

* inputN:

  - This function is somewhat underspecified for n=0. In particular,
    may it block? Is it required to raise Io if the underlying
    reader is closed?

* input, input1, inputN, inputAll:

  - (pedantic) Descriptions speak of "underlying system calls",
    although the reader may not actually depend on system calls.
    Preferably speak of "underlying reader" only.

* closeIn:

  - Likewise, description speaks of "releasing system resources".
    This should be replaced by saying that it closes the underlying
    reader (which is not even specified as is).

* closeOut:

  - Does the function attempt to close the stream even if flushing
    fails?

  - Why is it possible to close terminated streams? That seems to
    allow unfortunate interference with another stream that has been
    created from the extracted writer.

* mkInstream, getReader:

  - The table seems to imply that mkInstream always augments its
    reader. This is inappropriate for concurrent environments (see
    above).

  - Should getReader return the original or the augmented reader?

  - The table still includes the removed getPosIn and setPosIn
    functions.

* mkOutstream, getWriter:

  - Likewise.

* filePosIn:

  - There seems to be no way to implement this function for buffered
    I/O, because the reader position that corresponds to a
    mid-block-element is not available and cannot be calculated in
    general. So how is this meant?

  - Typo, s/character/element/

* filePosOut:

  - Likewise.

* getWriter:

  - It is non-obvious what the precise meaning of "terminating" a
    stream is. If this is merely setting a status flag then a
    corresponding note would be helpful.

* getPosOut:

  - May this flush the stream (and hence raise Io exceptions)?

* setPosOut:

  - This may raise an exception because the position has been
    invalidated after obtaining it (e.g. by file truncation
    performed by another process).

  - Typo, s/underlying device/underlying writer/

* setBufferMode, getBufferMode:

  - There is no specification of the semantics of line buffering, in
    particular for non-text streams.
    (See also comments on StreamIO functor)

  - It is not specified whether the stream may be flushed when set
    to LINE_BUF mode (may cause Io exception). It seems unreasonable
    to require it not to do so (assuming that line buffering is
    intended to maintain the invariant that the buffer never
    contains line breaks).

  - The synopsis of this function uses "ostr", while all others
    use "f" for streams.

* setPosOut, setBufferMode, getWriter:

  - Can raise an exception if flushing fails.

* Discussion:

  - The statement that closing a stream just causes the
    not-yet-determined part of the stream to be empty should
    probably be generalised to explain what *truncating* a stream
    means (getReader also truncates the stream).

  - Example of freshly opened stream:
    s/mkInstream r/mkInstream(r, vector [])/
    s/size/length/

  - nreads example:
    s/mkInstream r/mkInstream(r, vector [])/
    s/size/length/

  - input1/inputN relation example:
    (1) Inconsistent with the actual typing of input1 (see above).

    (2) Typo, s/inputN f/inputN(f,1)/

  - Unbuffered I/O, 1st example:
    (1) Typos,
    s/mkInstream(reader)/mkInstream(reader, vector [])/
    s/PrimIO.Rd{chunkSize,...}/(PrimIO.RD{chunksize,...}, v)/

    (2) More importantly, the actual condition appears to be
    incorrect. It should read:
    (chunkSize > 1 orelse length v = 1) andalso endOfStream f'

  - Unbuffered I/O, 2nd example:
    s/mkInstream(reader)/mkInstream(reader, vector [])/
    s/PrimIO.Rd{chunkSize,...}/(PrimIO.RD{chunksize,...}, v)/
    The condition must be corrected as above.

* There is no reference to the StreamIO functor.



The StreamIO functor
--------------------

* General problems:

  - It is impossible for this functor to support line buffering,
    since it has no way of knowing which element consists a line
    break. This could be solved by changing the someElem functor
    argument to a breakElem argument.

  - It is also impossible to utilize reader's endPos for
    pre-allocation, because the functor is parametric in the
    position type.

* Functor argument:

  - Since the extract and copy functions have been removed/changed
    from ARRAY and VECTOR signatures, the StreamIO functor now
    naturally requires slice structures for efficient
    implementation. (Likewise the PrimIO functor)

* Functor result:

  - Type sharing of the result types is not specified.

* Discussion, paragraph on flushing:

  - Most of this discussion rather belongs to the description of
    STREAM_IO.

  - Everything said here is not restricted to flushOut, but applies
    to flushing in general.

  - Unfortunately, it is left unspecified where flushing may happen
    and, consequently, where respective Io exceptions may occur.

  - Write retries as suggested here seem to be impossible to
    implement correctly using the writer interface as specified (see
    comments on PRIM_IO.writer).

  - According to the writer description, write operations may never
    return an element count of 0, so the last sentence is
    misleading.

* Discussion, last paragraph:

  - Typo, missing ")"

* Implementation note:

  - 3rd bullet: typo, s/PrimIO.augmentIn/PrimIO.augmentReader/

  - 5th and 6th bullet: The endPos function cannot be utilized as
    suggested, because the functor is necessarily parametric in the
    position type.



The IMPERATIVE_IO signature
---------------------------

* General comment:

  - It is unfortunate that imperative I/O is asymmetric with respect
    to providing (limited) random access on input vs. output streams
    - the former requires going down to the lower-level stream I/O.
    That makes imperative I/O a somewhat incomplete abstraction
    layer.

  - Likewise, it would be desirable if there were ways for
    performing full-fledged random access without leaving the
    imperative I/O abstraction layer, at least for streams were it
    is suitable (e.g. BinIO). Despite the statement in the
    discussion this is neither available for input nor for output
    streams (see comments below).

* closeIn:

  - Typo, s/S.closeIn/StreamIO.closeIn/

* flushOut:

  - Typo, s/S.flushOut/StreamIO.flushOut/

* closeOut:

  - Typo, s/S.closeOut/StreamIO.closeOut/

* Discussion:

  - Equivalences, last line: s/StreamIO.output/StreamIO.flushOut/

  - Paragraph about random-access on output streams: It says that
    BinIO.StreamIO.out_pos = Position.int. This is not true, we have
    BinPrimIO.pos = Position.int, but that is a completely different
    type. In fact, it is impossible to implement out_pos as
    Position.int.

* There is no reference to the ImperativeIO functor.



The ImperativeIO functor
------------------------

* Functor argument:

  - The Array argument is unnecessary.

* Functor result:

  - Type sharing of the result types is not specified.



The TEXT_STREAM_IO signature
----------------------------

* General comment:

  - Why bother separating this signature from STREAM_IO?
    => outputSubstr can easily be generalised to outputSlice
       (for good),
    => if line buffering is part of STREAM_IO, inputLine
       might be as well.



The TextIO structure
--------------------

* General comment:

  - Systems providing WideText should also provide a WideTextIO
    structure (they have to provide WideTextPrimIO already, which
    seems inconsistent).

* Interface:

  - Duplicated type constraints for StreamIO.reader and
    StreamIO.writer.



The BinIO structure
--------------------

* Interface:

  - Type sharing with BinPrimIO is not specified (unlike for
    TextIO), i.e. the following constraints are missing:

        where type StreamIO.reader = BinPrimIO.reader
        where type StreamIO.writer = BinPrimIO.writer
        where type StreamIO.pos = BinPrimIO.pos

******************************************************************************
******************************************************************************
******************************************************************************
******************************************************************************

Doing host/network byte order conversions on ML side.

Socket.Ctl
* Semantics of setNBIO, getNREAD, getATMARK are unclear;
  Don't seem to be accessible via {get,set}sockopt;
  Instead, using ioctl.

******************************************************************************
******************************************************************************

Posix.FileSys:
* Within structure S, the type mode is constrained equal to flags,
  but flags is an eqtype.

STREAM_IO.pos
* "This is the type of positions in the underlying readers and
  writers. In some instantiations of this signature (e.g.,
  TextIO.StreamIO), pos is abstract; in others (e.g., BinIO.StreamIO)
  it is Position.int."  But, the equality of BinIO.StreamIO.pos and
  Position.int is never specified in any where constraint of BinIO.
* How can filePosIn be implemented with completely abstract pos?

Not sent to list:

* (In general, probably a good idea to look at the entire top-level
  structure/signature matches and choose a consistent usage of base
  types.  For example, Int:>INTEGER would seem to hide the top-level
  int; unless Int is opened afterwards.  But, then what about all the
  other structures that reference int?  Is top-level int = Int.int or
  is Int.int = top-level int.)
--> I think I'm biased from looking at the MLton implementation,
becuase I'm finding it hard to think about how to really express all
of the sharing constraints in a way that will be acceptable.  This
might be the wrong way to look at things: the listing of structures
and signatures with clauses doesn't correspond to a build order, it
corresponds to the way the environment should look to the program.

Sequences and Slices:
Why not existsi, alli?

Vector:
Why no vector: int * 'a -> 'a vector?


Resolved:

If one defines VECTOR_SLICE by including a type 'a vector and replace
'a Vector.vector with the local 'a vector, but then binds
structure Vector: VECTOR
structure VectorSlice: VECTOR_SLICE where type 'a vector = 'a Vector.vector
at the top-level, does one violate the basis spec?
Rationale: it's easiset to implement Vector and VectorSlice
simultaneously, say with VectorSlice as a substructure of Vector (in
fact, with all of the Vector operations being dispatched to the
corresponding VectorSlice ops with full slices), so Vector isn't in
scope for the VECTOR_SLICE.
*** No, it's not o.k., because opening VectorSlice will introduce a binding
    for 'a vector; but, if we're lucky, John will accept the proposal.

IEEEReal:
toString prepends a #"~" even when the class is NAN?
*** I guess this is o.k.; there is an explicit sign field.

PACK_WORD:
structure Pack<N>Big :> PACK_WORD  (* OPTIONAL *)
structure Pack<N>Little :> PACK_WORD  (* OPTIONAL *)
but PACK_WORD has
val subVec  : Word8Vector.vector * int -> LargeWord.word
i.e., reference to LargeWord.word.
Should it be
PACK_WORD
type word
val subVec  : Word8Vector.vector * int -> word
with
structure Pack<N>Big :> PACK_WORD with word = Word<N>.word  (* OPTIONAL *)
Should there be PackBig and PackLittle with word = Word.word?
Should there be PackLargeBig with word = LargeWord.word?
There aren't many structures that refine on LargeXYZ; most refine on XYZ<N>.
*** O.k., we always unpack into a LargeWord, which we could then
    Word<N>.fromLargeWord back to the size.  I guess this is o.k.; It
    lets an implementation give more Pack<N>Big structures than there
    are Word<N> structures.

MLton specific:
 + why are Int32_gtu and Int32_geu primitive?
   Why not just Word.fromInt and use Word comparisons?
 + Real:>REAL doesn't match basis because it may peform
    arithmetic at extended precision.  Should this be mentioned
    in the user guide?
 + QUESTION: proc-env.sml
 + QUESTION: char.sml
 + check uses of {Vector,Array}Slice.slice for replacement by unsafeSlice.


******************************************************************************
******************************************************************************

UNIX:
I'm not quite sure how the ('a, 'b) proc type is supposed to work in
practice; The old Unix structure just used them as
TextIO.{in,out}streams.  My suspicion is that we're supposed to use
Posix.IO.mk{Bin,Text}{Reader,Writer} functions and then use the type
system to ensure that if we force a stream to be bin or text, then all
other uses have to be the same.  I also suspect that we're only
supposed to lift the file_desc up to an instream/outstream once; i.e.,
multiple textInstreamOf calls should continue to return the same
TextIO.instream.  That would seem to suggest we need an 'a option ref
that can be banged at the first call to a streamOf function, and
subsequent calls just return the value there.

textInstreamOf pr
binInstreamOf pr
    return a text or binary instream connected to the standard output
    stream of the process pr. Note the multiple calls to these
    functions on the same proc will result in multiple streams that
    all share the same underlying Unix stream.

textOutstreamOf pr
binOutstreamOf pr
    return a text or binary outstream connected to the standard input
    stream of the process pr. Note the multiple calls to these
    functions on the same proc will result in multiple streams that
    all share the same underlying Unix stream.

streamsOf pr
    returns a pair of input and output text streams associated with
    pr. This function is equivalent to (textInstream pr, textOutstream
    pr) and is provided for backward compatibility.