## MLton 20241230

# MLtonStructure

The `MLton` structure contains a lot of functionality that is not available in the Basis Library. As a warning, please keep in mind that the `MLton` structure and its substructures do change from release to release of MLton.

    structure MLton:
       sig
          val eq: 'a * 'a -> bool
          val equal: 'a * 'a -> bool
          val hash: 'a -> Word32.word
          val isMLton: bool
          val share: 'a -> unit
          val shareAll: unit -> unit
          val size: 'a -> IntInf.int
          val sizeAll: 'a -> IntInf.int

          structure Array: MLTON_ARRAY
          structure BinIO: MLTON_BIN_IO
          structure CharArray: MLTON_MONO_ARRAY where type t = CharArray.array
                                                where type elem = CharArray.elem
          structure CharVector: MLTON_MONO_VECTOR where type t = CharVector.vector
                                                  where type elem = CharVector.elem
          structure Cont: MLTON_CONT
          structure Exn: MLTON_EXN
          structure Finalizable: MLTON_FINALIZABLE
          structure GC: MLTON_GC
          structure IntInf: MLTON_INT_INF
          structure Itimer: MLTON_ITIMER
          structure LargeReal: MLTON_REAL where type t = LargeReal.real
          structure LargeWord: MLTON_WORD where type t = LargeWord.word
          structure Platform: MLTON_PLATFORM
          structure Pointer: MLTON_POINTER
          structure ProcEnv: MLTON_PROC_ENV
          structure Process: MLTON_PROCESS
          structure Profile: MLTON_PROFILE
          structure Random: MLTON_RANDOM
          structure Real: MLTON_REAL where type t = Real.real
          structure Real32: sig
                               include MLTON_REAL
                               val castFromWord: Word32.word -> t
                               val castToWord: t -> Word32.word
                            end where type t = Real32.real
          structure Real64: sig
                               include MLTON_REAL
                               val castFromWord: Word64.word -> t
                               val castToWord: t -> Word64.word
                            end where type t = Real64.real
          structure Rlimit: MLTON_RLIMIT
          structure Rusage: MLTON_RUSAGE
          structure Signal: MLTON_SIGNAL
          structure Syslog: MLTON_SYSLOG
          structure TextIO: MLTON_TEXT_IO
          structure Thread: MLTON_THREAD
          structure Vector: MLTON_VECTOR
          structure Weak: MLTON_WEAK
          structure Word: MLTON_WORD where type t = Word.word
          structure Word8: MLTON_WORD where type t = Word8.word
          structure Word16: MLTON_WORD where type t = Word16.word
          structure Word32: MLTON_WORD where type t = Word32.word
          structure Word64: MLTON_WORD where type t = Word64.word
          structure Word8Array: MLTON_MONO_ARRAY where type t = Word8Array.array
                                                 where type elem = Word8Array.elem
          structure Word8Vector: MLTON_MONO_VECTOR where type t = Word8Vector.vector
                                                   where type elem = Word8Vector.elem
          structure World: MLTON_WORLD
       end

## Substructures

- MLtonArray

- MLtonBinIO

- MLtonCont

- MLtonExn

- MLtonFinalizable

- MLtonGC

- MLtonIntInf

- MLtonIO

- MLtonItimer

- MLtonMonoArray

- MLtonMonoVector

- MLtonPlatform

- MLtonPointer

- MLtonProcEnv

- MLtonProcess

- MLtonRandom

- MLtonReal

- MLtonRlimit

- MLtonRusage

- MLtonSignal

- MLtonSyslog

- MLtonTextIO

- MLtonThread

- MLtonVector

- MLtonWeak

- MLtonWord

- MLtonWorld

## Values

- `eq (x, y)`

  returns true if `x` and `y` are equal as pointers. For simple types like `char`, `int`, and `word`, this is the same as equals. For arrays, datatypes, strings, tuples, and vectors, this is a simple pointer equality. The semantics is a bit murky.

- `equal (x, y)`

  returns true if `x` and `y` are structurally equal. For equality types, this is the same as PolymorphicEquality. For other types, it is a conservative approximation of equivalence.

- `hash x`

  returns a structural hash of `x`. The hash function is consistent between execution of the same program, but may not be consistent between different programs.

- `isMLton`

  is always `true` in a MLton implementation, and is always `false` in a stub implementation.

- `share x`

  maximizes sharing in the heap for the object graph reachable from `x`.

- `shareAll ()`

  maximizes sharing in the heap by sharing space for equivalent immutable objects. A call to `shareAll` performs a major garbage collection, and takes time proportional to the size of the heap.

- `size x`

  returns the amount of heap space (in bytes) taken by the value of `x`, including all objects reachable from `x` by following pointers. It takes time proportional to the size of `x`. See below for an example.

- `sizeAll ()`

  returns the amount of heap space (in bytes) taken by all reachable live data. It takes time proportional to the size of live data.

## Example of `MLton.size`

This example, `size.sml`, demonstrates the application of `MLton.size` to many different kinds of objects.

    fun 'a printSize (name: string, value: 'a, use: 'a -> unit): unit=
       (print "The size of "
        ; print name
        ; print " is "
        ; print (IntInf.toString (MLton.size value))
        ; print " bytes.\n"
        ; use value)

    fun chk (x, y) =
       if x = y
          then ()
          else raise Fail "bug"

    val l = [1, 2, 3, 4]

    val _ =
       (printSize ("a char", #"c", fn _ => ())
        ; printSize ("an int list of length 4",
                     List.tabulate (4, fn i => i + 1), fn l =>
                     chk (foldl (op +) 0 l, 10))
        ; printSize ("a string of length 10",
                     CharVector.tabulate (10, fn i => chr (ord #"0" + i)), fn s =>
                     chk (CharVector.foldl (fn (c,s) => ord c + s) 0 s,  525))
        ; printSize ("an int array of length 10",
                     Array.tabulate (10, fn i => i), fn a =>
                     chk (Array.foldl (op +) 0 a, 45))
        ; printSize ("a double array of length 10",
                     Array.tabulate (10, real), fn a =>
                     chk (Real.floor (Array.foldl (op +) 0.0 a), 45))
        ; printSize ("an array of length 10 of 2-ples of ints",
                     Array.tabulate (10, fn i => (i, i + 1)), fn a =>
                     chk (Array.foldl (fn ((a,b),s) => a + b + s) 0 a, 100))
        ; printSize ("a useless function",
                     fn _ => 13, fn f => ())
        )

    local
       open MLton.Cont
    in
       val rc: int option t option ref = ref NONE
       val _ =
          case callcc (fn k: int option t => (rc := SOME k; throw (k, NONE))) of
             NONE => ()
           | SOME i => print (concat [Int.toString i, "\n"])
    end

    val _ = printSize ("a continuation option ref",
                       rc, fn rc =>
                       case !rc of
                          NONE => ()
                        | SOME k => (rc := NONE; MLton.Cont.throw (k, SOME 13)))

Compile and run as usual.

    % mlton size.sml
    % ./size
    The size of a char is 0 bytes.
    The size of an int list of length 4 is 96 bytes.
    The size of a string of length 10 is 40 bytes.
    The size of an int array of length 10 is 64 bytes.
    The size of a double array of length 10 is 104 bytes.
    The size of an array of length 10 of 2-ples of ints is 104 bytes.
    The size of a useless function is 0 bytes.
    The size of a continuation option ref is 5016 bytes.
    13
    The size of a continuation option ref is 16 bytes.

Note that sizes are dependent upon the target platform and compiler optimizations.