- name: measure_ordinal_type_mismatch
  id: 019a0286-44a9-7900-927e-f307d9c1a59c
  created_at: '2025-10-20T16:49:05.193889+00:00'
  kind: TypeErr
  msg_str: |-
    Expression is expected to have type `Ordinal.t`,
    but its inferred type is `int`.
  tags: []
  repro_iml: |
    type action = Identity | Increment | Decrement

    let apply_action (act : action) (x : int) : int =
      match act with
      | Identity -> x
      | Increment -> x + 1
      | Decrement -> x - 1

    let process_actions_measure (actions : action list) (state : int) : int =
      List.length actions

    let rec process_actions (actions : action list) (state : int) : int =
      match actions with
      | [] -> state
      | act :: rest ->
          let new_state = apply_action act state in
          process_actions rest new_state
    [@@measure process_actions_measure actions state]
  err_msg:
    msg: 'Expression is expected to have type `Ordinal.t`,

      but its inferred type is `int`.'
    locs:
    - file: <none>
      start:
        line: 18
        col: 12
      stop:
        line: 18
        col: 48
    backtrace: null
  is_po_err: false
  solution: |
    type action = Identity | Increment | Decrement

    let apply_action (act : action) (x : int) : int =
      match act with
      | Identity -> x
      | Increment -> x + 1
      | Decrement -> x - 1

    let process_actions_measure (actions : action list) (state : int) : Ordinal.t =
      Ordinal.of_int (List.length actions)

    let rec process_actions (actions : action list) (state : int) : int =
      match actions with
      | [] -> state
      | act :: rest ->
          let new_state = apply_action act state in
          process_actions rest new_state
    [@@measure process_actions_measure actions state]
  explanation: |
    Termination measures in IML must return `Ordinal.t`, not `int`. The `[@@measure ...]`
    attribute expects a function that returns an ordinal value to prove well-founded recursion.
  solution_description: |
    Wrap the measure function's return value with `Ordinal.of_int` to convert int to Ordinal.t.
- name: function_list_first_order_violation
  id: 019a0286-469d-7671-b131-f20ac5694e07
  created_at: '2025-10-20T16:49:05.693916+00:00'
  kind: ValidationError
  msg_str: |-
    Function definition is not valid:
    Functions must return a first-order type,
    but `ls_f` returns `(int -> int) list`
  tags: []
  repro_iml: |
    let f (x : int) : int = x + 1

    let ls_f = [f; f; f]
  err_msg:
    msg: 'Function definition is not valid:

      Functions must return a first-order type,

      but `ls_f` returns `(int -> int) list`'
    locs:
    - file: <none>
      start:
        line: 3
        col: 1
      stop:
        line: 3
        col: 20
    backtrace: null
  is_po_err: false
  solution: |
    let f (x : int) : int = x + 1

    type action =
      | AddOne
      | AddTwo
      | AddThree

    let apply_action (act : action) (x : int) : int =
      match act with
      | AddOne -> x + 1
      | AddTwo -> x + 2
      | AddThree -> x + 3

    let ls_actions = [AddOne; AddOne; AddOne]
  explanation: |
    IML enforces a first-order type restriction: functions cannot be elements of composite types
    (lists, tuples, records, or algebraic data types). This is required for the formal semantics
    and automated reasoning capabilities.
  solution_description: |
    Use an algebraic data type to represent different actions instead of storing functions.
- name: max_int_not_available
  id: 019a0286-48af-7942-b19e-005ff59f2214
  created_at: '2025-10-20T16:49:06.223739+00:00'
  kind: TypeErr
  msg_str: |-
    Unknown identifier "max_int".
  tags: []
  repro_iml: |
    let clamp (x : int) : int =
      if x > max_int then
        max_int
      else
        x
  err_msg:
    msg: Unknown identifier "max_int".
    locs:
    - file: <none>
      start:
        line: 2
        col: 10
      stop:
        line: 2
        col: 16
    backtrace: null
  is_po_err: false
  solution: |
    let max_allowed = 1000000

    let clamp (x : int) : int =
      if x > max_allowed then
        max_allowed
      else
        x
  explanation: |
    IML integers have arbitrary precision, so there is no built-in `max_int` constant.
    Unlike OCaml which has bounded integers, IML can represent arbitrarily large integers.
  solution_description: |
    Use a specific constant for your use case.
  solution_description_2: |
    Make max_int opaque if it's externally defined.
  solution_2: |
    let max_int : int = () [@@opaque]

    let clamp (x : int) : int =
      if x > max_int then
        max_int
      else
        x
- name: let_star_binding_not_in_scope
  id: 019a0286-4a9d-7863-a315-8526247455d1
  created_at: '2025-10-20T16:49:06.717731+00:00'
  kind: TypeErr
  msg_str: |-
    Unknown identifier "let*".
  tags: []
  repro_iml: |
    let process_options (x : int option) (y : int option) : int option =
      let* x_val = x in
      let* y_val = y in
      Some (x_val + y_val)
  err_msg:
    msg: Unknown identifier "let*".
    locs:
    - file: <none>
      start:
        line: 2
        col: 3
      stop:
        line: 2
        col: 6
    backtrace: null
  is_po_err: false
  solution: |
    let process_options (x : int option) (y : int option) : int option =
      let open Option in
      let* x_val = x in
      let* y_val = y in
      Some (x_val + y_val)
  explanation: |
    The `let*` binding operator is part of the Option module but not available globally.
    It needs to be brought into scope by opening the Option module or using qualified syntax.
  solution_description: |
    Open the Option module to use let* binding operator.
  solution_description_2: |
    Use explicit Option.flat_map.
  solution_2: |
    let process_options (x : int option) (y : int option) : int option =
      Option.flat_map (fun x_val ->
        Option.flat_map (fun y_val ->
          Some (x_val + y_val)
        ) y
      ) x
  solution_description_3: |
    Use >>= operator with Option module open.
  solution_3: |
    let process_options (x : int option) (y : int option) : int option =
      Option.(x >>= fun x_val ->
      y >>= fun y_val ->
      Some (x_val + y_val))
- name: real_pow_exponent_must_be_int
  id: 019a0286-4c86-7fa2-8928-62fe7e2a5c40
  created_at: '2025-10-20T16:49:07.206536+00:00'
  kind: TypeErr
  msg_str: |-
    Application failed: expected argument of type `Int.t`
    but got (exponent : real)
  tags: []
  repro_iml: |
    let calculate (n : int) : real =
      let base = 2.5 in
      let exponent = Real.of_int (n / 41670) in
      Real.pow base exponent
  err_msg:
    msg: 'Application failed: expected argument of type `Int.t`

      but got (exponent : real)'
    locs:
    - file: <none>
      start:
        line: 4
        col: 3
      stop:
        line: 4
        col: 24
    backtrace: null
  is_po_err: false
  solution: |
    let calculate (n : int) : real =
      let base = 2.5 in
      let exponent = Real.of_int (n / 41670) in
      Real.pow base (Real.to_int exponent)
  explanation: |
    `Real.pow` has signature `real -> int -> real`. The exponent must be an integer, not a real.
    This is because IML only supports integer exponentiation for exact arithmetic.
  solution_description: |
    Convert the exponent back to int using Real.to_int.
  solution_description_2: |
    Make a custom power function opaque for real exponents.
  solution_2: |
    let real_pow : real -> real -> real = () [@@opaque]

    let calculate (n : int) : real =
      let base = 2.5 in
      let exponent = Real.of_int (n / 41670) in
      real_pow base exponent
- name: list_fold_left2_not_available
  id: 019a0286-4e78-7c71-97b3-499001b04d3f
  created_at: '2025-10-20T16:49:07.704074+00:00'
  kind: TypeErr
  msg_str: |-
    Unknown function `List.fold_left2`.
  tags: []
  repro_iml: |
    let sum_pairs (l1 : int list) (l2 : int list) : int =
      List.fold_left2 (fun acc x y -> acc + x + y) 0 l1 l2
  err_msg:
    msg: Unknown function `List.fold_left2`.
    locs:
    - file: <none>
      start:
        line: 2
        col: 3
      stop:
        line: 2
        col: 17
    backtrace: null
  is_po_err: false
  solution: |
    let sum_pairs (l1 : int list) (l2 : int list) : int =
      match List.map2 (fun x y -> (x, y)) l1 l2 with
      | Error _ -> 0
      | Ok pairs -> List.fold_left (fun acc (x, y) -> acc + x + y) 0 pairs
  explanation: |
    `List.fold_left2` does not exist in IML's List module. IML has `List.map2` but not fold_left2.
  solution_description: |
    Use List.map2 to create pairs first, then fold.
  solution_description_2: |
    Implement custom recursive function.
  solution_2: |
    let rec sum_pairs (l1 : int list) (l2 : int list) : int =
      match l1, l2 with
      | [], [] -> 0
      | x :: xs, y :: ys -> x + y + sum_pairs xs ys
      | _, _ -> 0
- name: real_comparison_type_mismatch
  id: 019a0286-5097-75f3-a877-3ec308dd1a05
  created_at: '2025-10-20T16:49:08.247610+00:00'
  kind: TypeErr
  msg_str: |-
    Application failed: expected argument of type `int`
    but got (x : real)
  tags: []
  repro_iml: |
    let some_function (x : real) : real =
      if x > max_real then
        max_real
      else
        x
  err_msg:
    msg: 'Application failed: expected argument of type `int`

      but got (x : real)'
    locs:
    - file: <none>
      start:
        line: 2
        col: 6
      stop:
        line: 2
        col: 17
    backtrace: null
  is_po_err: false
  solution: |
    let max_real_bound = 1000000.0

    let some_function (x : real) : real =
      if x >. max_real_bound then
        max_real_bound
      else
        x
  explanation: |
    Two issues: (1) `max_real` is not a built-in constant in IML, and (2) the comparison
    operator `>` is for integers. Real comparison requires different operators like `>.`,
    `<.`, `>=.`, `<=.` (though the standard operators now work for reals too).
  solution_description: |
    Define a specific bound and use real comparison operator.
  solution_description_2: |
    Make max_real opaque and use >= which works for reals.
  solution_2: |
    let max_real : real = () [@@opaque]

    let some_function (x : real) : real =
      if x >= max_real then
        max_real
      else
        x
- name: array_not_available
  id: 019a0286-5277-7a42-80ff-597ed7177408
  created_at: '2025-10-20T16:49:08.727099+00:00'
  kind: TypeErr
  msg_str: |-
    Unknown identifier `Array.make`.
  tags: []
  repro_iml: |
    let example () =
      let arr = Array.make 5 0 in
      arr
  err_msg:
    msg: Unknown identifier `Array.make`.
    locs:
    - file: <none>
      start:
        line: 2
        col: 13
      stop:
        line: 2
        col: 22
    backtrace: null
  is_po_err: false
  solution: |-
    (* Use list instead of Array *)
    let example () =
      let arr = List.mapi (fun _ _ -> 0) (0 -- 5) in
      arr
  explanation: |
    Arrays are mutable data structures and not available in IML, which is a pure functional
    language without mutable state. All operations must be immutable.
  solution_description: |
    Use immutable lists with functional updates instead of arrays.
- name: option_map2_not_available
  id: 019a0286-5493-71c3-b4ef-40da25773fc8
  created_at: '2025-10-20T16:49:09.267802+00:00'
  kind: TypeErr
  msg_str: |-
    Unknown function `Option.map2`.
  tags: []
  repro_iml: |
    let add_options (x : int option) (y : int option) : int option =
      Option.map2 (fun a b -> a + b) x y
  err_msg:
    msg: Unknown function `Option.map2`.
    locs:
    - file: <none>
      start:
        line: 2
        col: 3
      stop:
        line: 2
        col: 13
    backtrace: null
  is_po_err: false
  solution: |
    let add_options (x : int option) (y : int option) : int option =
      Option.monoid_product x y |> Option.map (fun (a, b) -> a + b)
  explanation: |
    `Option.map2` does not exist in IML's Option module. Use `Option.monoid_product`
    or monadic composition instead.
  solution_description: |
    Use Option.monoid_product with map.
  solution_description_2: |
    Use let+ and and+ operators.
  solution_2: |
    let add_options (x : int option) (y : int option) : int option =
      let open Option in
      let+ a = x
      and+ b = y in
      a + b
  solution_description_3: |
    Use flat_map for monadic composition.
  solution_3: |
    let add_options (x : int option) (y : int option) : int option =
      Option.flat_map (fun a ->
        Option.map (fun b -> a + b) y
      ) x
- name: min_int_not_available
  id: 019a0286-566a-7653-9b5d-087b41db8c53
  created_at: '2025-10-20T16:49:09.738494+00:00'
  kind: TypeErr
  msg_str: |-
    Unknown identifier "min_int".
  tags: []
  repro_iml: |
    let clamp (x : int) : int =
      if x < min_int then
        min_int
      else
        x
  err_msg:
    msg: Unknown identifier "min_int".
    locs:
    - file: <none>
      start:
        line: 2
        col: 10
      stop:
        line: 2
        col: 16
    backtrace: null
  is_po_err: false
  solution: |
    let min_allowed = -1000000

    let clamp (x : int) : int =
      if x < min_allowed then
        min_allowed
      else
        x
  explanation: |
    Similar to `max_int`, IML does not have a built-in `min_int` constant because integers
    have arbitrary precision and can be arbitrarily small (negative).
  solution_description: |
    Use a specific constant.
  solution_description_2: |
    Make min_int opaque if it's externally defined.
  solution_2: |
    let min_int : int = () [@@opaque]

    let clamp (x : int) : int =
      if x < min_int then
        min_int
      else
        x
- name: option_bind_not_available
  id: 019a0286-5858-7b41-b195-70664dc7e57d
  created_at: '2025-10-20T16:49:10.232273+00:00'
  kind: TypeErr
  msg_str: |-
    Unknown function `Option.bind`.
  tags: []
  repro_iml: |
    let process (x : int option) : int option =
      Option.bind x (fun v -> Some (v + 1))
  err_msg:
    msg: Unknown function `Option.bind`.
    locs:
    - file: <none>
      start:
        line: 2
        col: 3
      stop:
        line: 2
        col: 13
    backtrace: null
  is_po_err: false
  solution: |
    let process (x : int option) : int option =
      Option.flat_map (fun v -> Some (v + 1)) x
  explanation: |
    In IML, the function is called `Option.flat_map` instead of `Option.bind`. The monadic
    bind operator is available as `>>=` within the Option module.
  solution_description: |
    Use Option.flat_map.
  solution_description_2: |
    Use >>= operator.
  solution_2: |
    let process (x : int option) : int option =
      Option.(x >>= fun v -> Some (v + 1))
  solution_description_3: |
    Use let* with open Option.
  solution_3: |
    let process (x : int option) : int option =
      let open Option in
      let* v = x in
      Some (v + 1)
- name: failwith_not_available
  id: 019a0286-5a37-7750-8303-e66e4ab445dd
  created_at: '2025-10-20T16:49:10.711885+00:00'
  kind: TypeErr
  msg_str: |-
    Unknown identifier "failwith".
  tags: []
  repro_iml: |
    let divide (x : int) (y : int) : int =
      if y = 0 then
        failwith "Division by zero"
      else
        x / y
  err_msg:
    msg: Unknown identifier "failwith".
    locs:
    - file: <none>
      start:
        line: 3
        col: 5
      stop:
        line: 3
        col: 12
    backtrace: null
  is_po_err: false
  solution: |
    let divide (x : int) (y : int) : int option =
      if y = 0 then
        None
      else
        Some (x / y)
  explanation: |
    IML is a pure language without exceptions. The `failwith` function from OCaml is not
    available. Error handling must use `Option` or `Result` types instead.
  solution_description: |
    Return an option type with None for error cases.
  solution_description_2: |
    Return a Result type with error message.
  solution_2: |
    let divide (x : int) (y : int) : (int, string) result =
      if y = 0 then
        Error "Division by zero"
      else
        Ok (x / y)
  solution_description_3: |
    Return a sentinel value (changes function signature semantics).
  solution_3: |
    let divide (x : int) (y : int) : int =
      if y = 0 then
        0
      else
        x / y
- name: ref_not_available
  id: 019a0286-5c27-7142-98f6-2ab8790eb27a
  created_at: '2025-10-20T16:49:11.207341+00:00'
  kind: TypeErr
  msg_str: |-
    Unknown identifier "ref".
  tags: []
  repro_iml: |
    let counter () =
      let count = ref 0 in
      count := !count + 1;
      !count
  err_msg:
    msg: Unknown identifier "ref".
    locs:
    - file: <none>
      start:
        line: 2
        col: 15
      stop:
        line: 2
        col: 17
    backtrace: null
  is_po_err: false
  solution: |
    let counter (count : int) : int =
      count + 1
  explanation: |
    References (`ref`) are mutable state and not available in IML, which is purely functional.
    All state changes must be explicit through function parameters and return values.
  solution_description: |
    Use a parameter to track state.
  solution_description_2: |
    Use recursion for stateful computation.
  solution_2: |
    let rec count_up_to (n : int) (current : int) : int =
      if current >= n then
        current
      else
        count_up_to n (current + 1)
  solution_description_3: |
    Return the new state explicitly.
  solution_3: |
    let increment (count : int) : int =
      count + 1

    let counter () : int =
      let count = 0 in
      let count = increment count in
      count
