```ml
let sample_type ty target =
    (* Base cases *)
    if target == 0 then
        return Some(Any)
    if target == ty.node_count then
        return Some(ty)

    match ty.term with
    | Any -> Some Any if target = 0 else None
    (* base types *)
    | Int | Bool -> Some ty if target = 1 else None
    (* nested types *)
    | Arrow of tys
        let* tys' = sample_type_list (target - 1) (ty.node_count - 1) in
        Some (Arrow tys')
    | Product of tys ->
        let* tys' = sample_type_list (target - 1) (ty.node_count - 1) in
        Some (Product tys')
    (* the rest are omitted for simplicity *)
```

```ml
let sample_type_list target potential types =
    if potential < target then
        return None
        
    result_list <- []
    picked_nodes <- 0
    remaining_potential <- potential
    
    (* Add indices for restoring the original order *)
    let indexed_types = enumerate(types)

    (* Perform weighted shuffle using the node count as the weight *)
    let shuffled_types = weighted_shuffle(indexed_types)

    for (index, ty) in shuffled_types:
        (* Calculate valid range for this type *)
        let max_nodes = ty.node_count in
        let lower_bound = max 0 (target - remaining_potential - picked_nodes) in
        let upper_bound = min max_nodes (target - picked_nodes) in
        
        (* Randomly choose number of nodes to be kept *)
        let nodes_to_use = random_int_in_range lower_bound upper_bound in

        let* sampled_type = sample_type ty nodes_to_use in

        result_list.append((index, sampled_type))
        picked_nodes += nodes_to_use
        remaining_potential -= max_nodes
        
    (* Restore original order *)
    reorder_by_index result_list
```


```ml
let sample_one target_interval potential types =
    result_list <- []
    picked_nodes <- 0
    remaining_potential <- potential

    let (lower, upper) = target_interval in
    for ty in types:
        if remaining_potential <= 0 then
            break

        let max_nodes = ty.node_count in
        remaining_potential -= max_nodes
        (* Calculate valid range for this type *)
        let lower_bound = max 0 (lower - remaining_potential - picked_nodes) in
        let upper_bound = min max_nodes (upper - picked_nodes) in
        (* Randomly choose number of nodes to be kept *)
        let nodes_to_use = random_int_in_range lower_bound upper_bound in
        (* Try to sample a less precise type *)
        let sampled_type = sample_type ty nodes_to_use in
        if sampled_type is not None then
            result_list.append((ty.annotation, ty'))
            picked_nodes += nodes_to_use
    result_list
```


```ml
let sample_many num_samples program types total_nodes interval =    
    results <- []
    
    (* Generate requested number of samples *)
    for i in range num_samples:
        (* Shuffle types randomly for this sample *)
        let shuffled_types = shuffle types in

        (* Generate one sample of type replacements *)
        let sample = sample_one interval total_nodes shuffled_types in

        (* Convert sample to hashtable *)
        let env = create_hashtable sample in

        (* Apply the type replacements to create new program *)
        let modified_program = replace_types env program in
        
        results.append(modified_program)
    
    results
```

```ml
let dynamize program num_samples num_bins =
    (* decorate types with the count of static type nodes *)
    let (types, total_nodes) = generate_lattice_info program in

    let intervals = generate_intervals num_bins (total_nodes / num_bins) in

    results <- []

    for interval in intervals:
        let samples = sample_many num_samples program types total_nodes interval in
        results.append(samples)

    results
```

```ml
val decorate_with_static_type_node_count : 'a program -> ('a, int) ty list

val generate_lattice_info : 'a program -> ('a, int) ty list * int

val generate_intervals
```

```ml
let f : int -> (int -> bool) = ... in
let x : ? = ... in
f x
```

```ml
[
  (Arrow ((Int, 1),
          (Arrow ((Int, 1), (Bool, 1)), 3)), 5) ;
  (Any, 0) ;
]
```
