# Option and Result types

**URL:** https://forum.ada-lang.io/t/option-and-result-types/824
**Category:** General
**Created:** [April 27, 2024, 7:21pm UTC](https://forum.ada-lang.io/t/option-and-result-types/824 "2024-04-27T19:21:15Z")
**Posts on this page:** 20
**Page:** 1

<div class="post-metadata">

### Author: ![benjamin-thomas](https://forum.ada-lang.io/user_avatar/forum.ada-lang.io/benjamin-thomas/32/422_2.png) [@benjamin-thomas](https://forum.ada-lang.io/u/benjamin-thomas)
#### Post date: [April 27, 2024, 7:21pm UTC](https://forum.ada-lang.io/t/option-and-result-types/824/1 "2024-04-27T19:21:15Z")

</div>

Hi!

I’m looking at the error handling story of Ada, which seems to be pretty much all-exception based (and “unchecked” in Java parlance).

An alternative to exceptions which I’ve learned to appreciate is the use of option/maybe types or result/either types. Because it forces the caller to check the possible error state, which is carried over by the type. It’s also possible to build “fallible pipelines” with it, a bit like legos.

These types have been incorporated into the latest C++ standard: [Functional exception-less error handling with C++23's optional and expected - C++ Team Blog](https://devblogs.microsoft.com/cppblog/cpp23s-optional-and-expected/)

So I’m wondering if there’s been any talk about this style of error handling in the Ada community? And dealing with null related errors in general.

---

<div class="post-metadata">

### Author: ![JeremyGrosser](https://forum.ada-lang.io/user_avatar/forum.ada-lang.io/jeremygrosser/32/3_2.png) [@JeremyGrosser](https://forum.ada-lang.io/u/JeremyGrosser)
#### Post date: [April 27, 2024, 8:30pm UTC](https://forum.ada-lang.io/t/option-and-result-types/824/2 "2024-04-27T20:30:51Z")

</div>

Option types can be modeled in Ada as a tagged type (class) or discriminated record. See the [optional](https://github.com/mosteo/optional/blob/1aa0e20bf7cd010c4b59e6ab7cc4b089790b796e/examples/optional-demo.adb) Alire crate for an example of the former.

Many embedded applications use `pragma Restriction (No_Exception_Propagation);`, which causes the application to “crash” if any exception is raised. In these environments, a common pattern is to provide an `out` argument for procedure status. Example:

```ada
type Status_Type is (Ok, Bus_Error, Value_Error);
procedure Bus_Write (Data : Data_Type; Status : out Status_Type);

```

With `SPARK_Mode => On`, gnatprove’s “silver” mode will verify Absence of Runtime Exceptions (AoRTE) at compile/verification time rather than runtime. gnatprove will also catch Constraint\_Errors raised by things like out of range integer assignments in this mode.

So yes, the full featured Ada language has runtime exceptions, but there are several options for avoiding or eliminating them in your application and with static verification.

---

<div class="post-metadata">

### Author: ![jere](https://forum.ada-lang.io/user_avatar/forum.ada-lang.io/jere/32/87_2.png) [@jere](https://forum.ada-lang.io/u/jere)
#### Post date: [April 28, 2024, 3:05am UTC](https://forum.ada-lang.io/t/option-and-result-types/824/3 "2024-04-28T03:05:56Z")

</div>

for simple types, I generally roll my own using a Variant record:

```ada
type Option(Valid : Boolean := False) is record
   case Valid is
      when False => null; -- nothing in the object when false
      when True => Value : My_Type; -- Value here when true
   end case;
end record;

```

Then you can just return one of those:

```ada
   Thing : Option := Some_Function;
begin
   if Thing.Valid then
      -- do stuff with Thing.Value
   end if;

```

You can use enumerations for error codes in place of the boolean as well:

```ada
type Error is (No_Error, Some_Error, Bad_Error);
type Option(Status : Error:= Bad_Error) is record
   case Valid is
      when No_Error => Value : My_Type; -- Value here when in error
      when others => null; -- nothing in the object when in error
   end case;
end record;

```

For unconstrained types and more complex types, the optional library linked above is pretty good.

---

<div class="post-metadata">

### Author: ![kevlar700](https://forum.ada-lang.io/user_avatar/forum.ada-lang.io/kevlar700/32/40_2.png) [@kevlar700](https://forum.ada-lang.io/u/kevlar700)
#### Post date: [April 28, 2024, 11:51am UTC](https://forum.ada-lang.io/t/option-and-result-types/824/4 "2024-04-28T11:51:20Z")

</div>

Unfortunately when a returned value is volatile then I believe the variant makes it incompatible with SPARK mode. You can mirror the value into a non-volatile type but then you have to ask yourself if it is worth it.

In general null and access types aren’t required much in Ada and access types can be designated as not null.

---

<div class="post-metadata">

### Author: ![jere](https://forum.ada-lang.io/user_avatar/forum.ada-lang.io/jere/32/87_2.png) [@jere](https://forum.ada-lang.io/u/jere)
#### Post date: [April 28, 2024, 12:50pm UTC](https://forum.ada-lang.io/t/option-and-result-types/824/5 "2024-04-28T12:50:45Z")

</div>

Yep, for volatile objects I generally return a non volatile copy rather than the object itself. I found in my experience it is best to limit volatile accesses to as few as possible and localized as much as possible to allow the compiler to optimize elsewhere. Anytime a type or object passed into or out of a function/procedure is volatile, I mark that as a code smell (not out of the box bad, but worthy of very focused review).

---

<div class="post-metadata">

### Author: ![kevlar700](https://forum.ada-lang.io/user_avatar/forum.ada-lang.io/kevlar700/32/40_2.png) [@kevlar700](https://forum.ada-lang.io/u/kevlar700)
#### Post date: [April 28, 2024, 2:13pm UTC](https://forum.ada-lang.io/t/option-and-result-types/824/6 "2024-04-28T14:13:11Z")

</div>

I used to do the same but I think I now disagree because there is little to no performance issue and when the svd file is corrected which happens a lot (or swapped out for a similar chip) then the maintainability is higher.

---

<div class="post-metadata">

### Author: ![kevlar700](https://forum.ada-lang.io/user_avatar/forum.ada-lang.io/kevlar700/32/40_2.png) [@kevlar700](https://forum.ada-lang.io/u/kevlar700)
#### Post date: [April 29, 2024, 11:32am UTC](https://forum.ada-lang.io/t/option-and-result-types/824/7 "2024-04-29T11:32:16Z")

</div>

So this got me thinking and using a subtype inherits Volatile but a new type copy doesn’t seem to. So I think you can drop the volatile issues but keep the maintainability of having e.g. one enum as the memory register itself.

```ada
Package Non_Volatile is
      type CFG2_COMM_Field is new STM32_SVD.SPI.CFG2_COMM_Field
end Non_Volatile;

```

It means conversions are required but that’s ok.

---

<div class="post-metadata">

### Author: ![benjamin-thomas](https://forum.ada-lang.io/user_avatar/forum.ada-lang.io/benjamin-thomas/32/422_2.png) [@benjamin-thomas](https://forum.ada-lang.io/u/benjamin-thomas)
#### Post date: [April 29, 2024, 7:19pm UTC](https://forum.ada-lang.io/t/option-and-result-types/824/8 "2024-04-29T19:19:47Z")

</div>

> [@JeremyGrosser](#):
>
> Option types can be modeled in Ada as a tagged type (class) or discriminated record. See the [optional](https://github.com/mosteo/optional/blob/1aa0e20bf7cd010c4b59e6ab7cc4b089790b796e/examples/optional-demo.adb) Alire crate for an example of the former.
> 
> Many embedded applications use `pragma Restriction (No_Exception_Propagation);`, which causes the application to “crash” if any exception is raised. In these environments, a common pattern is to provide an `out` argument for procedure status.

Great feedback, thanks! `pragma Restriction` sounds interesting.

> [@jere](#):
>
> for simple types, I generally roll my own using a Variant record:

I tried to play with that approach. But ideally, code like this should not compile when using an option type (conceptually I mean). That’s because you’re “forced” to unwrap the container type to then observe that something is present for use, or a type representing nothing.

```ada
with Ada.Text_IO;

procedure My_Program is
   package IO renames Ada.Text_IO;

   type My_Number is range 1 .. 10;

   type Option (Valid : Boolean := False) is record
      case Valid is
         when False =>
            null;
         when True =>
            Value : My_Number;
      end case;
   end record;

   Opt : Option := (Valid => False);
begin

   if not Opt.Valid then
      IO.Put_Line ("Values is:" & Opt.Value'Image);
   else
      IO.Put_Line ("No values");
   end if;

   IO.Put_Line ("Hello, World!!");

end My_Program;

```

---

<div class="post-metadata">

### Author: ![cantanima](https://forum.ada-lang.io/user_avatar/forum.ada-lang.io/cantanima/32/121_2.png) [@cantanima](https://forum.ada-lang.io/u/cantanima)
#### Post date: [April 29, 2024, 9:19pm UTC](https://forum.ada-lang.io/t/option-and-result-types/824/9 "2024-04-29T21:19:42Z")

</div>

Why not make the type generic?

---

<div class="post-metadata">

### Author: ![kevlar700](https://forum.ada-lang.io/user_avatar/forum.ada-lang.io/kevlar700/32/40_2.png) [@kevlar700](https://forum.ada-lang.io/u/kevlar700)
#### Post date: [May 3, 2024, 11:06am UTC](https://forum.ada-lang.io/t/option-and-result-types/824/11 "2024-05-03T11:06:58Z")

</div>

Slight improvement. There is actually no benefit of avoiding volatile when it is as in the usual case an input but this does regain nicer/exact selection semantics in the IDE as I would normally design into my own types.

```ada
Package Non_Volatile is
   Package CFG2_COMM is
      type Field is new STM32_SVD.SPI.CFG2_COMM_Field
   end CFG2_COMM;
end Non_Volatile;

```

p.s. I do not use package use clauses.

---

<div class="post-metadata">

### Author: ![kevlar700](https://forum.ada-lang.io/user_avatar/forum.ada-lang.io/kevlar700/32/40_2.png) [@kevlar700](https://forum.ada-lang.io/u/kevlar700)
#### Post date: [November 5, 2024, 1:12pm UTC](https://forum.ada-lang.io/t/option-and-result-types/824/12 "2024-11-05T13:12:36Z")

</div>

> [@jere](#):
>
> You can use enumerations for error codes in place of the boolean as well:

If you keep the status or error code as a separate out parameter from the option/result record then you will be warned by the compiler if you do not check it which is more important than the option type in the first place, in my opinion. -gnatw.o

---

<div class="post-metadata">

### Author: ![OneWingedShark](https://forum.ada-lang.io/user_avatar/forum.ada-lang.io/onewingedshark/32/305_2.png) [@OneWingedShark](https://forum.ada-lang.io/u/OneWingedShark)
#### Post date: [November 7, 2024, 3:16pm UTC](https://forum.ada-lang.io/t/option-and-result-types/824/13 "2024-11-07T15:16:34Z")

</div>

> [@benjamin-thomas](#):
>
> An alternative to exceptions which I’ve learned to appreciate is the use of option/maybe types or result/either types.

This is flatly incorrect — ‘option’ is **not** a method for handling errors.

> [@benjamin-thomas](#):
>
> So I’m wondering if there’s been any talk about this style of error handling in the Ada community? And dealing with null related errors in general.

It’s not a method of handling errors… but that style can be done with definite-types and arrays: using this:

```ada
Subtype Option_Index is Boolean range True..True;
Type Optional is Array(Option_Index range <>) of ELEMENT_TYPE;
None : Constant Optional := (True..False => DUMMY_VAL); -- 0 length array.
Function "+"(Item : ELEMENT_TYPE) return Optional is
   ( True => Item );

```

And then for accessing the optional value:

```ada
Procedure Some_Operation(Object : Optional) is
Begin
  EXAMPLE:
  For Item of Object loop
    Print_Value_or_whatever( Item );
  End loop EXAMLPE;
End Some_Operation;

```

---

<div class="post-metadata">

### Author: ![OneWingedShark](https://forum.ada-lang.io/user_avatar/forum.ada-lang.io/onewingedshark/32/305_2.png) [@OneWingedShark](https://forum.ada-lang.io/u/OneWingedShark)
#### Post date: [November 7, 2024, 3:18pm UTC](https://forum.ada-lang.io/t/option-and-result-types/824/14 "2024-11-07T15:18:49Z")

</div>

Ada does not have generic types.

---

<div class="post-metadata">

### Author: ![cantanima](https://forum.ada-lang.io/user_avatar/forum.ada-lang.io/cantanima/32/121_2.png) [@cantanima](https://forum.ada-lang.io/u/cantanima)
#### Post date: [November 7, 2024, 3:32pm UTC](https://forum.ada-lang.io/t/option-and-result-types/824/15 "2024-11-07T15:32:04Z")

</div>

Weirdly, I know that. At a distance of more than 6 months, I think I meant to ask, “Why not make the package generic?”

---

<div class="post-metadata">

### Author: ![benjamin-thomas](https://forum.ada-lang.io/user_avatar/forum.ada-lang.io/benjamin-thomas/32/422_2.png) [@benjamin-thomas](https://forum.ada-lang.io/u/benjamin-thomas)
#### Post date: [November 8, 2024, 7:22am UTC](https://forum.ada-lang.io/t/option-and-result-types/824/16 "2024-11-08T07:22:28Z")

</div>

> [@OneWingedShark](#):
>
> This is flatly incorrect — ‘option’ is **not** a method for handling errors.

It’s an established pattern for error handling that came from functional programming and making its way to mainstream languages (Rust has it, C++ is getting it as I linked in my introduction post). But perhaps you had something else in mind?

Here’s a couple of refs to drive the point:

- [Error Handling · OCaml Documentation](https://ocaml.org/docs/error-handling#using-the-option-type-for-errors)

> The **`option`** module provides the first alternative to exceptions. The `'a option` data type represents either data of type `'a` - for instance, `Some 42` is of type `int option` - or the absence of data due to any error as `None` .

- [Data.Maybe](https://hackage.haskell.org/package/base-4.20.0.1/docs/Data-Maybe.html)

> The `Maybe` type encapsulates an optional value. A value of type `Maybe` a either contains a value of type `a` (represented as `Just` a), or it is empty (represented as `Nothing` ). Using `Maybe` is a good way to deal with errors or exceptional cases without resorting to drastic measures such as `error` .

To be fair, I played with the C++ implementation since I posted and I found the implementation a little bit “clunky”. Still, I think it’s nice tool to have in your toolbox.

Here’s how you can define Option and Result types in TypeScript

* * *

`Option` may contain a value. To access the value, you are forced to “unwrap” this container at which point you’ll have “something” with a value or “nothing”.

```typescript
interface None {
    readonly kind: 'None';
}

interface Some<A> {
    readonly kind: 'Some';
    readonly val: A;
}

type Option<A> = None | Some<A>;

```

* * *

`Result` may contain a value (of type `A`), and if not it provides an error with a value of type `B` (rather than “nothing”)

```typescript
interface Err<T> {
    readonly kind: 'Err';
    readonly val: T;
}

interface Ok<T> {
    readonly kind: 'Ok';
    readonly val: T;
}

type Result<A, B> = Err<A> | Ok<B>;

```

* * *

These are not convential types in TypeScript btw, but the type system is flexible enough to allow expressing them.

Without having generic types (in the “generics” sens), it sounds like a deadend though.

For the interest of the discussion, I’ll note that Kotlin also has a Result type (with its own twist on things), but no Option type : [Result - Kotlin Programming Language](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-result/)

---

<div class="post-metadata">

### Author: ![OneWingedShark](https://forum.ada-lang.io/user_avatar/forum.ada-lang.io/onewingedshark/32/305_2.png) [@OneWingedShark](https://forum.ada-lang.io/u/OneWingedShark)
#### Post date: [November 8, 2024, 2:43pm UTC](https://forum.ada-lang.io/t/option-and-result-types/824/17 "2024-11-08T14:43:39Z")

</div>

> [@benjamin-thomas](#):
>
> It’s an established pattern for error handling that came from functional programming and making its way to mainstream languages (Rust has it, C++ is getting it as I linked in my introduction post). But perhaps you had something else in mind?

It’s not actually error-handling because it isn’t about error-states; exceptions and error-codes are error-handling (and exceptions can be used for non-exceptional signaling in addition to handling an error-state). — “Option” is more about data-structuring.

I can see how someone could confuse it and think it is about error-handling, but it’s really more about the processing of a list of items (namely 0- or 1-length).

If you structure your program in that list-processing manner then you can go from 0/1 to any size with [generally speaking] minimal refactor because you’re already handling the possibility of variance, rather than having THE data-item… and then having to deal with the absence.

---

<div class="post-metadata">

### Author: ![kevlar700](https://forum.ada-lang.io/user_avatar/forum.ada-lang.io/kevlar700/32/40_2.png) [@kevlar700](https://forum.ada-lang.io/u/kevlar700)
#### Post date: [November 8, 2024, 7:23pm UTC](https://forum.ada-lang.io/t/option-and-result-types/824/18 "2024-11-08T19:23:44Z")

</div>

> [@benjamin-thomas](#):
>
> It’s an established pattern for error handling

I can see it being somewhat analogous to double entry accounting. I’m not sure whether it will actually catch any bugs that aren’t just the engineer being extremely sloppy. I can see it working or being reassuring for out parameters but what does Rust do about it’s equivalent of in out? Then you might want to have a readable parameter with a failure status. Then it becomes confusing on the API side.

---

<div class="post-metadata">

### Author: ![cantanima](https://forum.ada-lang.io/user_avatar/forum.ada-lang.io/cantanima/32/121_2.png) [@cantanima](https://forum.ada-lang.io/u/cantanima)
#### Post date: [November 8, 2024, 10:19pm UTC](https://forum.ada-lang.io/t/option-and-result-types/824/19 "2024-11-08T22:19:09Z")

</div>

> [@kevlar700](#):
>
> I can see it working or being reassuring for out parameters but what does Rust do about it’s equivalent of in out?

I only recall seeing Rust’s `Option` used as a return or an `in` type, not for `out` parameters, let alone `in out` parameters. I’m sure it can be used that way, but it would feel awfully clunky.

The point of `Option` is that a variable might not have a valid value; hence the variants are `Some` and `None`. Safe Rust requires the use of initialized variables only, so `&mut` parameters (the Rust version of `in out`) don’t really make sense as `Option` types, unless you’re trying to avoid the initialization, and in that case I don’t see why you wouldn’t prefer to pass the parameter as `&` (no `mut`) and `return` it instead, which seems more idiomatic (in my experience).

_added in update:_ see this [comment](https://www.reddit.com/r/rust/comments/vgalq3/comment/id0nu4h/?utm_source=share&utm_medium=web3x&utm_name=web3xcss&utm_term=1&utm_content=share_button), or indeed the entire thread, which seems to confirm my experience

---

<div class="post-metadata">

### Author: ![kevlar700](https://forum.ada-lang.io/user_avatar/forum.ada-lang.io/kevlar700/32/40_2.png) [@kevlar700](https://forum.ada-lang.io/u/kevlar700)
#### Post date: [November 8, 2024, 10:41pm UTC](https://forum.ada-lang.io/t/option-and-result-types/824/20 "2024-11-08T22:41:12Z")

</div>

Say you have a package with a function that provides a list type. Perhaps you would want to have a result option type where you wouldn’t have access to the list if something went wrong creating it. Another function operates on a successfully created list. Instead of both taking list. In Rust would one be list and one is option wrapping list. Isn’t that a little unneat/clunky? Isn’t the status/result type then inconsistent also? I tried to look at some rust crates but that didn’t help much. Perhaps I will have another look.

---

<div class="post-metadata">

### Author: ![jere](https://forum.ada-lang.io/user_avatar/forum.ada-lang.io/jere/32/87_2.png) [@jere](https://forum.ada-lang.io/u/jere)
#### Post date: [November 8, 2024, 11:27pm UTC](https://forum.ada-lang.io/t/option-and-result-types/824/21 "2024-11-08T23:27:57Z")

</div>

Rust has built in language level pattern matching constructs for option and result types, so it usually isn’t clunky. You get the option type and then can call the other functions using something like `if let` or `match` constructs.

[Next page](https://forum.ada-lang.io/t/option-and-result-types/824.md?page=2)
