# When to use iarray instead of array?

**URL:** https://discuss.ocaml.org/t/when-to-use-iarray-instead-of-array/17838
**Category:** Learning
**Created:** [February 21, 2026, 9:48pm UTC](https://discuss.ocaml.org/t/when-to-use-iarray-instead-of-array/17838 "2026-02-21T21:48:46Z")
**Posts on this page:** 17
**Page:** 1

<div class="post-metadata">

### Author: ![jbe](https://avatars.discourse-cdn.com/v4/letter/j/f6c823/32.png) [@jbe](https://discuss.ocaml.org/u/jbe)
#### Post date: [February 21, 2026, 9:48pm UTC](https://discuss.ocaml.org/t/when-to-use-iarray-instead-of-array/17838/1 "2026-02-21T21:48:46Z")

</div>

Stumbling upon this other thread, I realized that OCaml has support for immutable arrays:

> [@Constant parameters in OCaml?](https://discuss.ocaml.org/t/constant-parameters-in-ocaml/15050/4):
>
> Incidentally, for the case of arrays, the addition of immutable arrays is being discussed upstream: [Immutable arrays by OlivierNicole · Pull Request #13097 · ocaml/ocaml · GitHub](https://github.com/ocaml/ocaml/pull/13097).

And indeed, those are part of OCaml 5.4: module [`Iarray`](https://ocaml.org/manual/5.4/api/Iarray.html) and also a type `iarray` (for which I don’t seem to find an entry in the manual [here](https://ocaml.org/manual/5.4/core.html); maybe it is missing in the manual?).

It doesn’t have an indexing operator ([#13784](https://github.com/ocaml/ocaml/issues/13784)), but you can [define one](https://github.com/ocaml/ocaml/issues/13784).

I struggle a bit when and how to use that new type. In my case, I have written a solver for linear equation systems using the Gauss method. I would like the types to be something like:

```auto
val solve : (Num.t iarray * Num.t) list -> Num.t array option

```

with some generic number module `Num`.

I don’t want the function to modify/destroy the input arguments. So I assume changing my function to accept an `iarray` is fine? But while I’m calculating the output, as a last step of the Gauss algorithm, I keep the numbers in a mutable array anyway. So is it reasonable to return that mutable array instead of converting it into an immutable array? (Afterall, some future users of my function might want to modify the result.)

Or should I stick to one kind of array and use it consistently for input and output?

What are other people’s experiences with using `iarray`? I noticed that refactoring my code to use `iarray` instead of `array` is quite a lot of work, especially as I will have to do that replacement in _some_ places, while in others I need to keep mutability. So I would need to duplicate some code, e.g. here in my tests (using [Alcotest](https://github.com/mirage/alcotest/blob/main/README.md)):

```diff
 (** Tests rational numbers ([Q.t]). *)
 let testable_q : Q.t Alcotest.testable = Alcotest.testable Q.pp_print Q.equal
 
 (** Tests rational vectors (i.e. arrays of rational numbers). *)
 let testable_qvec = Alcotest.array testable_q
+
+(** Tests immutable rational vectors. *)
+let testable_qivec =
+ Alcotest.testable
+ (fun f x -> Format.pp_print_array Q.pp_print f (Iarray.to_array x))
+ (Iarray.for_all2 Q.equal)

```

Also note that there doesn’t seem to be an `Alcotest.iarray`, so I have to convert my `iarray` first to an `array` before `Alcotest` is able to process it. Either by providing a corresponding [`testable`](https://mirage.github.io/alcotest/alcotest/Alcotest/index.html#type-testable) as above, or by manually converting all `iarrays` into `array` before letting `Alcotest` process them.

Is this friction going to be better within time (possibly leading to more duplication in libraries?), or is `iarray` more to be seen as a special type that you only use when you _really_ need it, and otherwise stick to `array` and/or making types abstract when you want to avoid access from outside?

---

<div class="post-metadata">

### Author: ![otini](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/otini/32/3533_2.png) [@otini](https://discuss.ocaml.org/u/otini)
#### Post date: [February 21, 2026, 10:59pm UTC](https://discuss.ocaml.org/t/when-to-use-iarray-instead-of-array/17838/2 "2026-02-21T22:59:32Z")

</div>

> [@jbe](#):
>
> And indeed, those are part of OCaml 5.4: module [`IArray`](https://ocaml.org/manual/5.4/api/Iarray.html) and also a type `iarray` (for which I don’t seem to find an entry in the manual [here](https://ocaml.org/manual/5.4/core.html); maybe it is missing in the manual?).

The intention is that people should rather use `Iarray.t`, and `iarray` is a built-in type that is more an implementation detail that may disappear from the interface. (In fact, we should rewrite this API to expose `'a Iarray.t` rather than `'a iarray`).

> [@jbe](#):
>
> I don’t want the function to modify/destroy the input arguments. So I assume changing my function to accept an `iarray` is fine? But while I’m calculating the output, as a last step of the Gauss algorithm, I keep the numbers in a mutable array anyway. So is it reasonable to return that mutable array instead of converting it into an immutable array? (Afterall, some future users of my function might want to modify the result.)
> 
> Or should I stick to one kind of array and use it consistently for input and output?

The intention of immutable arrays is mostly to have better APIs: documenting that functions do not modify their arguments for instance.

So it’s up to you and to how you think your API should be used. If it’s convenient for your users to be able to modify the result of a function, maybe you should use a mutable array.

> [@jbe](#):
>
> But while I’m calculating the output, as a last step of the Gauss algorithm, I keep the numbers in a mutable array anyway.

Note that `Dynarray.unsafe_to_iarray` exists, i.e., turning a mutable (and dynamically-sized) array to an iarray without a copy (under some conditions).

> [@jbe](#):
>
> Also note that there doesn’t seem to be an `Alcotest.iarray`, so I have to convert my `iarray` first to an `array` before `Alcotest` is able to process it. Either by providing a corresponding [`testable`](https://mirage.github.io/alcotest/alcotest/Alcotest/index.html#type-testable) as above, or by manually converting all `iarrays` into `array` before letting `Alcotest` process them.

Since `Iarray.t` is in the stdlib, I think it would make sense to suggest to the alcotest maintainers to add `Alcotest.iarray`.

---

<div class="post-metadata">

### Author: ![jbe](https://avatars.discourse-cdn.com/v4/letter/j/f6c823/32.png) [@jbe](https://discuss.ocaml.org/u/jbe)
#### Post date: [February 22, 2026, 8:38am UTC](https://discuss.ocaml.org/t/when-to-use-iarray-instead-of-array/17838/3 "2026-02-22T08:38:54Z")

</div>

> [@otini](#):
>
> The intention is that people should rather use `Iarray.t`, and `iarray` is a built-in type that is more an implementation detail that may disappear from the interface.

Oh, that is good to know.

> [@otini](#):
>
> (In fact, we should rewrite this API to expose `'a Iarray.t` rather than `'a iarray`).

Yeah, the documentation of the `Iarray` module doesn’t just mention `iarray` in [`type 'a t`](https://ocaml.org/manual/5.4/api/Iarray.html#TYPEt), but `iarray` is mentioned in every function there, e.g. [`iter`](https://ocaml.org/manual/5.4/api/Iarray.html#VALiter). If `iarray` is really an implementation detail, it’s somewhat misleading as of yet.

So thank you for letting me know.

> [@otini](#):
>
> The intention of immutable arrays is mostly to have better APIs: documenting that functions do not modify their arguments for instance.

Reading in the comments on the corresponding pull-request #13097, I found some thought by @charguer that seems to be contrary to that:

> **[charguer](https://github.com/charguer)** commented [on May 14, 2024](https://github.com/ocaml/ocaml/pull/13097#issuecomment-2109540935):
> 
> […]
> 
> The notion of immutable arrays is useful as a typing information. Sometimes, you’d like the array to be unmodified by a function, but subsequently recover the ability to modify it. For that, you need more than types, something like separation logic permissions. […]

Specifically, say an algorithm X creates an array that it needs to modify and – during its runtime at several stages – algorithm X calls several functions (`f1`, `f2`, …) that do not modify the array. If those functions use `Iarray.t` to document that they don’t modify their argument, then calling [`Iarray.to_array`](https://ocaml.org/manual/5.4/api/Iarray.html#VALto_array) will require X to create a copy each time of the array (unless we use some unsafe magic, I think?).

On the other hand, if another algorithm Y works with an array that it does _not_ need to modify an array, and if (`f1`, `f2`, …) were designed such that they accept an `array` instead of an `iarray` (so that they are more performant when used by algorithm X), then using `f1`, `f2`, … in algorithm Y would require to needlessly create a mutable array for each invocation of `f1`, `f2`, …

This is because `Iarray.t` (to my understanding) gives more guarantees than “this function will not modify its argument”. It also reflects a guarantee _by the caller_ that the array won’t be modified, so we have a two-sided guarantee here. Passing an argument `a : Iarray.t` to a function `f` guarantees that:

- Function `f` will not modify `a`.
- No parallel task will modify `a`.
- No functions invoked during `f`’s runtime will modify `a`.
- No functions invoked after `f` returned will modify `a`.

I cannot just express the first guarantee (function `f` will not modify `a`) by replacing an `array` argument with an `Iarray.t` argument without _additionally_ requiring the latter three guarantees _by the caller_ as well, which causes (in my example above) X to create a copy each time of the array.

This concurs with some in the remainder of the above cited comment in the PR:

> The notion of immutable arrays is useful to enable compiler optimizations […]

* * *

> [@otini](#):
>
> Note that `Dynarray.unsafe_to_iarray` exists, i.e., turning a mutable (and dynamically-sized) array to an iarray without a copy (under some conditions).

It only exists for `Dynarray` but not for ~~`Iarray`~~ `Array`? Is there a reason for that? _(edit: I thinkI found the answer [below](https://discuss.ocaml.org/t/when-to-use-iarray-instead-of-array/17838/6).)_ (Generally, I would probably not want to use unsafe functions for my use-case, but I’m curious.)

---

<div class="post-metadata">

### Author: ![jbe](https://avatars.discourse-cdn.com/v4/letter/j/f6c823/32.png) [@jbe](https://discuss.ocaml.org/u/jbe)
#### Post date: [February 22, 2026, 10:56am UTC](https://discuss.ocaml.org/t/when-to-use-iarray-instead-of-array/17838/4 "2026-02-22T10:56:29Z")

</div>

The following isn’t meant as a suggestions how to idiomatically write code, but to understand the underlying nature of “I accept an array that I won’t modify” in an as-abstract-as-possible way (i.e. without demanding additional guarantees made by the caller as pointed out in my previous post). I think the answer is abstract types. I would probably express it as follows:

```ocaml
module type Parray = sig
  type 'a t

  val of_array : 'a array -> 'a t
  val of_iarray : 'a Iarray.t -> 'a t
  val to_array : 'a t -> 'a array
  val to_iarray : 'a t -> 'a Iarray.t
  val get : 'a t -> int -> 'a
end

module Parray1 : Parray = struct
  type 'a t = 'a array

  let of_array = Fun.id
  let of_iarray = Iarray.to_array
  let to_array = Fun.id
  let to_iarray = Iarray.of_array
  let get = Array.get
end

module Parray2 : Parray = struct
  type 'a t = 'a Iarray.t

  let of_array = Iarray.of_array
  let of_iarray = Fun.id
  let to_array = Iarray.to_array
  let to_iarray = Fun.id
  let get = Iarray.get
end

module M (Parr : Parray) = struct
  let algorithm : int Parr.t -> int =
    fun arr ->
      Parr.get arr 0 + Parr.get arr 1
end

module M1 = M (Parray1)
module M2 = M (Parray2)

let _ =
  let a1 : _ array = [| 12; 13; 102 |] in
  assert (M1.algorithm (Parray1.of_array a1) = 25);
  assert (M2.algorithm (Parray2.of_array a1) = 25);
  let a2 : _ Iarray.t = [| 12; 13; 102 |] in
  assert (M1.algorithm (Parray1.of_iarray a2) = 25);
  assert (M2.algorithm (Parray2.of_iarray a2) = 25)

```

Here, the algorithm (`algorithm`) is provided as part of a functor, allowing it to work both with `array` and `Iarray.t`, depending on what the caller provides.

In particular, if a caller already happens to have a mutable array, we can instantiate the functor such that converting the mutable array into the abstract type is a no-op: `Parray1.of_array a1` is simply `a1`. Accordingly, if a caller happens to have an immutable array, we can instantiate the functor such that converting the immutable array into the abstract type is a no-op: `Parray2.of_iarray a2` is simply `a2`.

Now I don’t want to propose providing a generic interface like `Parray` above. But what I wonder is: Perhaps I should consider whether I’m using `array` or `Iarray.t` as an implementation detail that should not be exposed in my API anyway and instead use abstract types (as also suggested to me in [another context](https://discuss.ocaml.org/t/selectively-bringing-constructors-or-record-fields-into-scope/17821/7)).

Getting back to my Gauss solver, perhaps an equation should be an abstract type that can be constructed by lists, mutable arrays, immutable arrays, etc. And my implementation decides when or if a conversion is required. Something like:

```auto
module type Number = sig
  type t
  (* ... *)
end

module Equation (Num : Number) : sig
  type t

  val make : Num.t Seq.t -> Num.t -> t
  val make_array : Num.t array -> Num.t -> t
  val make_iarray : Num.t Iarray.t -> Num.t -> t
end = struct
  (* The choice for [t] might have an effect on performance,
     depending on whether users of the API primarily use
     [make_array] or [make_iarray]. *)
  type t = Num.t Iarray.t * Num.t

  let make lhs rhs = (Iarray.of_seq lhs, rhs)
  let make_array lhs rhs = (Iarray.of_array lhs, rhs)
  let make_iarray lhs rhs = (lhs, rhs)
end

```

I feel like choosing `array` vs `Iarray.t` is not really a matter of designing interfaces but rather a matter of what kind of _implementation_ of arrays I want to (or should) use in a specific scenario. Any thoughts on that?

* * *

_P.S.:_ Note that in my example above, `make_array` could or could not demand in its documentation/contract that the array is held constant while the resulting `Equation.t` is used.

---

<div class="post-metadata">

### Author: ![cvine](https://avatars.discourse-cdn.com/v4/letter/c/90db22/32.png) [@cvine](https://discuss.ocaml.org/u/cvine)
#### Post date: [February 22, 2026, 12:31pm UTC](https://discuss.ocaml.org/t/when-to-use-iarray-instead-of-array/17838/5 "2026-02-22T12:31:22Z")

</div>

> [@jbe](#):
>
> Yeah, the documentation of the `Iarray` module doesn’t just mention `iarray` in [`type 'a t`](https://ocaml.org/manual/5.4/api/Iarray.html#TYPEt), but `iarray` is mentioned in every function there, e.g. [`iter`](https://ocaml.org/manual/5.4/api/Iarray.html#VALiter). If `iarray` is really an implementation detail, it’s somewhat misleading as of yet.

The documentation also does not indicate that the Iarray module is available since 5.4 unlike, say, Dynarray (since 5.2), Seq (since 4.07) or Bytes (since 4.02). It would be nice to have consistency.

---

<div class="post-metadata">

### Author: ![jbe](https://avatars.discourse-cdn.com/v4/letter/j/f6c823/32.png) [@jbe](https://discuss.ocaml.org/u/jbe)
#### Post date: [February 22, 2026, 12:42pm UTC](https://discuss.ocaml.org/t/when-to-use-iarray-instead-of-array/17838/6 "2026-02-22T12:42:36Z")

</div>

> [@jbe](#):
>
> > [@otini](#):
> >
> > Note that `Dynarray.unsafe_to_iarray` exists, […]
> 
> It only exists for `Dynarray` but not for `Iarray`? Is there a reason for that? […]

I guess that for unsafely converting an `array` to an `Iarray.t`, I simply would use [`Obj.magic`](https://ocaml.org/manual/5.4/api/Obj.html#VALmagic), e.g.:

```auto
let unsafe_array_to_iarray : 'a array -> 'a Iarray.t = Obj.magic
let unsafe_iarray_to_array : 'a Iarray.t -> 'a array = Obj.magic

```

---

<div class="post-metadata">

### Author: ![jbe](https://avatars.discourse-cdn.com/v4/letter/j/f6c823/32.png) [@jbe](https://discuss.ocaml.org/u/jbe)
#### Post date: [February 22, 2026, 12:54pm UTC](https://discuss.ocaml.org/t/when-to-use-iarray-instead-of-array/17838/7 "2026-02-22T12:54:59Z")

</div>

Re-thinking about this, I think when not modifying the input, I have more choices than just `Iarray.t` and `array`:

- use `array`,
- use `Iarray.t`,
- do not expose the type, i.e. use generic types such that the implementation isn’t exposed,
- use a different type such as lists or [sequences](https://ocaml.org/manual/5.4/api/Seq.html).

I feel like which of those choices is best depends on the specific case. I do _not_ think using `Iarray.t` is the general answer to “my function doesn’t modify the argument”. In my case, if I copy the argument as part of my algorithm, maybe even a sequence is the better choice over an immutable array.

---

<div class="post-metadata">

### Author: ![otini](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/otini/32/3533_2.png) [@otini](https://discuss.ocaml.org/u/otini)
#### Post date: [February 22, 2026, 1:02pm UTC](https://discuss.ocaml.org/t/when-to-use-iarray-instead-of-array/17838/8 "2026-02-22T13:02:56Z")

</div>

> The documentation also does not indicate that the Iarray module is available since 5.4

Hmm… yet [there is](https://github.com/ocaml/ocaml/blob/trunk/stdlib/iarray.mli) a `@since` annotation at the top of the file. Maybe the doc generator is bamboozled by the `open!` annotation.

---

<div class="post-metadata">

### Author: ![otini](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/otini/32/3533_2.png) [@otini](https://discuss.ocaml.org/u/otini)
#### Post date: [February 22, 2026, 1:25pm UTC](https://discuss.ocaml.org/t/when-to-use-iarray-instead-of-array/17838/9 "2026-02-22T13:25:16Z")

</div>

@jbe Yes, your safest bet is to expose an abstract type and a minimal API.

> [@jbe](#):
>
> I guess that for unsafely converting an `array` to an `Iarray.t`, I simply would use [`Obj.magic`](https://ocaml.org/manual/5.4/api/Obj.html#VALmagic), e.g.:
> 
> ```auto
> let unsafe_array_to_iarray : 'a array -> 'a Iarray.t = Obj.magic
> let unsafe_iarray_to_array : 'a Iarray.t -> 'a array = Obj.magic
> 
> ```

Unsafely, yes.

> [@jbe](#):
>
> It only exists for `Dynarray` but not for `Iarray`? Is there a reason for that?

I assume you mean for `Array`. Well, a dynarray that doesn’t change size is essentially an array, so the dynarray function seems to mostly subsume that use case.

---

<div class="post-metadata">

### Author: ![jbe](https://avatars.discourse-cdn.com/v4/letter/j/f6c823/32.png) [@jbe](https://discuss.ocaml.org/u/jbe)
#### Post date: [February 22, 2026, 1:27pm UTC](https://discuss.ocaml.org/t/when-to-use-iarray-instead-of-array/17838/10 "2026-02-22T13:27:26Z")

</div>

> [@otini](#):
>
> Since `Iarray.t` is in the stdlib, I think it would make sense to suggest to the alcotest maintainers to add `Alcotest.iarray`.

I made a corresponding proposal:

> <https://github.com/mirage/alcotest/issues/434>
>
> As \[Iarray.t\](https://ocaml.org/manual/5.4/api/Iarray.html) is exposed as part o…f OCaml's standard library (version 5.4) now, it would be nice if a corresponding \`Alcotest.iarray\` was added to Alcotest:
> 
> \`\`\`ocaml
> val 'a testable -\> 'a Iarray.t testable
> \`\`\`
> 
> Note that OCaml's documentation currently wrongly exposes \`iarray\` as a type, which seems to be an implementation detail though that shouldn't have been exposed (see \[this forum post\](https://discuss.ocaml.org/t/when-to-use-iarray-instead-of-array/17838/2?u=jbe)). So \`Iarray.t\` should be used instead when referring to OCaml's immutable array type (of course, the \`testable\` could still be named \`Alcotest.iarray\`).

---

<div class="post-metadata">

### Author: ![jbe](https://avatars.discourse-cdn.com/v4/letter/j/f6c823/32.png) [@jbe](https://discuss.ocaml.org/u/jbe)
#### Post date: [February 22, 2026, 1:41pm UTC](https://discuss.ocaml.org/t/when-to-use-iarray-instead-of-array/17838/11 "2026-02-22T13:41:23Z")

</div>

> [@otini](#):
>
> I assume you mean for `Array`.

Yes, my apologies, I did add an edit to my post above to avoid confusion:

> [@jbe](#):
>
> It only exists for `Dynarray` but not for ~~`Iarray`~~ `Array`?

> [@otini](#):
>
> Well, a dynarray that doesn’t change size is essentially an array, so the dynarray function seems to mostly subsume that use case.

What I meant is: Why isn’t the a function that unsafely converts an `Array` into an `Iarray`, but as I noticed above, there is [`Obj.magic`](https://ocaml.org/manual/5.4/api/Obj.html#VALmagic), which does the job already.

---

<div class="post-metadata">

### Author: ![otini](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/otini/32/3533_2.png) [@otini](https://discuss.ocaml.org/u/otini)
#### Post date: [February 22, 2026, 1:58pm UTC](https://discuss.ocaml.org/t/when-to-use-iarray-instead-of-array/17838/12 "2026-02-22T13:58:23Z")

</div>

> What I meant is: Why isn’t the a function that unsafely converts an `Array` into an `Iarray`, but as I noticed above, there is [`Obj.magic`](https://ocaml.org/manual/5.4/api/Obj.html#VALmagic), which does the job already.

Yes, and exposing a function that does Obj.magic, even with “unsafe” in the name, would be questionable because the situations where it’s safe to use would depend on the optimizations performed. So we may as well let people use Obj.magic and know they’re on their own.

---

<div class="post-metadata">

### Author: ![EmileTrotignon](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/emiletrotignon/32/5913_2.png) [@EmileTrotignon](https://discuss.ocaml.org/u/EmileTrotignon)
#### Post date: [February 23, 2026, 9:20am UTC](https://discuss.ocaml.org/t/when-to-use-iarray-instead-of-array/17838/13 "2026-02-23T09:20:55Z")

</div>

I am guessing that a possible use of a specialized function is to change the type of the array without being able the change the type of the elements. You can annotate your use of Obj.magic for that, but its not by default.

---

<div class="post-metadata">

### Author: ![octachron](https://avatars.discourse-cdn.com/v4/letter/o/49beb7/32.png) [@octachron](https://discuss.ocaml.org/u/octachron)
#### Post date: [February 23, 2026, 9:23am UTC](https://discuss.ocaml.org/t/when-to-use-iarray-instead-of-array/17838/14 "2026-02-23T09:23:39Z")

</div>

> [@jbe](#):
>
> there is [`Obj.magic`](https://ocaml.org/manual/5.4/api/Obj.html#VALmagic), which does the job already.

Note that the only job that `Obj.magic` is doing is breaking your code. The `Obj.magic` function is not part of the language, and using it means giving free reign to compiler optimisations to break your code. And lying over the mutability of data is a particularly dangerous game.

---

<div class="post-metadata">

### Author: ![jbe](https://avatars.discourse-cdn.com/v4/letter/j/f6c823/32.png) [@jbe](https://discuss.ocaml.org/u/jbe)
#### Post date: [February 23, 2026, 9:52am UTC](https://discuss.ocaml.org/t/when-to-use-iarray-instead-of-array/17838/15 "2026-02-23T09:52:52Z")

</div>

> [@octachron](#):
>
> The `Obj.magic` function is not part of the language, and using it means giving free reign to compiler optimisations to break your code.

Yeah, thanks for pointing that out. I was also misunderstanding how [`Dynarray.unsafe_to_iarray`](https://ocaml.org/manual/5.4/api/Dynarray.html#VALunsafe_to_iarray) works. I thought it converts the types (under certain conditions), but actually it calls a function that must exhibit specific behavior for the whole procedure to be sound.

I don’t plan to use `Obj.magic` any time soon anyway, but thanks for the warning and notice that `Obj.magic` is _ **not** _ suitable to convert `array` ↔ `Iarray.t`.

---

<div class="post-metadata">

### Author: ![vlaviron](https://avatars.discourse-cdn.com/v4/letter/v/ec9cab/32.png) [@vlaviron](https://discuss.ocaml.org/u/vlaviron)
#### Post date: [February 23, 2026, 10:29am UTC](https://discuss.ocaml.org/t/when-to-use-iarray-instead-of-array/17838/16 "2026-02-23T10:29:56Z")

</div>

Please note that `array` and `iarray` are fundamentally incompatible types. They happen to share implementation details, but `iarray`s are not `array`s that are exposed as immutable.  
In particular, a function that takes an `iarray` must be able to rely on the fact that nobody else can mutate the argument.  
If you want to document that some functions do not mutate their arguments but still need to use mutable arrays for the rest of your code, my advice is to define an `ArrayView` module like this:

```ocaml
module ArrayView : sig
  type 'a t
  val from_array : 'a array -> 'a t
  val get : 'a t -> int -> 'a
  ...
end = struct
  type 'a t = 'a array
  let from_array a = a
  let get = Array.get
  ...
end

```

This module does not export a `to_array` function, and no mutating functions either. This means that by passing `ArrayView.from_array a` to a function, you have the guarantee that the function will not be able to mutate the array but you can keep the ability to mutate it yourself safely.

---

<div class="post-metadata">

### Author: ![jbe](https://avatars.discourse-cdn.com/v4/letter/j/f6c823/32.png) [@jbe](https://discuss.ocaml.org/u/jbe)
#### Post date: [February 23, 2026, 10:37am UTC](https://discuss.ocaml.org/t/when-to-use-iarray-instead-of-array/17838/17 "2026-02-23T10:37:25Z")

</div>

> [@vlaviron](#):
>
> If you want to document that some functions do not mutate their arguments but still need to use mutable arrays for the rest of your code, my advice is to define an `ArrayView` module like this: […]

I think that roughly corresponds to my `Parray1` [example above](https://discuss.ocaml.org/t/when-to-use-iarray-instead-of-array/17838/4) (for which I also provided an abstraction `Parray`, which generalizes over non-modified `array`s and `Iarray.t`s). But I guess it’s overkill in most scenarios, and such invariants can better be documented as part of the documentation rather than using the type system, I guess. Afterall, OCaml can’t fully reflect side-effects in its type system anyway.
