DEV Community

david2am
david2am

Posted on • Edited on

When Failure is Not an Option: A Practical Case for OCaml


Photo from Louis Hansel in Unsplash

Sources


🟣 A New Perspective on Programming

Don't take me wrong, we do great things on the Web, and there are a lot of smart people working on it but I started to feel that I needed more within programming from a year ago.

Curiosity lead me to system's level programming languages, I learned some C and C++ in the university, but I wanted something less intimidating than C or Rust and more performant than JavaScript or Python, in other words, something in between.

So I learn a bit of Zig (in my opinion a wonderful programming language), I enjoyed it but I felt the trade-off between fine-grained control and rapid productivity, so... I needed something else.


🟣 The "Aha!" Moment

I used to hear Developer Voices, a YouTube channel directed by Kris Jenkins, and one day I heard a conversation between Kris and a guy, Leandro Ostera, about this programming language called OCaml 🐪, to be honest I didn't get much, I just heard about functional programming here an there and this catchy phrase "OCaml my Caml!" that I didn't get 😆 but by listening Leandro I realized that he also experienced this "should be more out there" sensation, so I felt connected, and to my surprise the programming language he talked seems to be in the sweet spot I was looking for: something performant and expressive without much sacrifices.

So I used my spare time to learn about OCaml, tried it a little bit and after some time I'm still in love and I want to share with you some of the reasons I think it's especial:

  • It's elegant and effective in the real world.
  • It has a friendly community of very talented people.
  • There are some companies that express such confidence in the language that built their entire organizations in OCaml's shoulders.

🟣 The Five Pillars of OCaml

You might be thinking, "I can do all of this in my current language." And you're probably right. But let me ask you: how confident are you in the code you just wrote? Would you bet your company's critical system on it?

At least in the TypeScript world, we often add state machine libraries to gain a high degree of confidence and predictability, but that means extra dependencies, complexity, and more things that could break.

With OCaml, that confidence comes built-in, the language itself is your safety net:

  • Performance: It offers native compilation and static typing without sacrificing expressiveness.
  • Correctness: It helps you deliver what you intended with safety and reliability baked in.
  • Dexterity: It gives you the power and agility to get things done quickly, efficiently, and safely.
  • Functional It's easy to reason about.
  • Practical When purity introduce complexity OCaml introduce simplicity.

Let's see how this works in practice.


🟣 Performance: Speed Without Sacrifice

OCaml is a compiled, statically-typed language that offers a rare combination of high-level expressiveness and raw performance.

  • Its native code compiler produces fast, optimized executables.
  • It provides zero-cost abstractions, so you can write elegant and declarative code without a performance penalty.
  • Its predictable garbage collector is ideal for low-latency systems.

In other words, OCaml let you focus on your business logic without a performance penalty.

🟣 Correctness: Your Built-in Safety Net

Thinking in Edge Cases

I mentioned before that as web developers we gain confidence using state machine libraries, OCaml in another hand, give you the same with two built-in features: types and pattern-matching.

For example: OCaml's compiler forces you to consider edge cases from the beginning:

let my_favorite_language (my_favorite :: the_rest) = my_favorite;;
(* Warning 8 [partial-match]: this pattern-matching is not exhaustive.
Here is an example of a case that is not matched:
[] *)
Enter fullscreen mode Exit fullscreen mode

You're encouraged to handle all possibilities using pattern matching, a powerful feature that's like a switch statement on steroids.

let my_favorite_language languages =
  match languages with
  | first :: the_rest -> first
  | [] -> "OCaml" (* A sensible default! *)
Enter fullscreen mode Exit fullscreen mode

Making Illegal States Unrepresentable

This is OCaml's superpower. Imagine you have a shape type:

type shape =
  | Circle of float
  | Rectangle of float * float
Enter fullscreen mode Exit fullscreen mode

When business requirements change and you need to add a Triangle, you simply update the type:

type shape =
  | Circle of float
  | Rectangle of float * float
  | Triangle of float * float  (* base, height *)
Enter fullscreen mode Exit fullscreen mode

The compiler then becomes your assistant, pointing out every function that doesn't yet handle Triangle.

let area shape =
  match shape with
  | Circle radius -> Float.pi *. radius ** 2.
  | Rectangle (width, height) -> width *. height

(*
  Error (warning 8): this pattern-matching is not exhaustive.
  Here is an example of a case that is not matched:
  Triangle (_, _)
 *)
Enter fullscreen mode Exit fullscreen mode

Now your business logic is encoded directly in the type system. Once you fix the compiler errors, you can be confident that the code is correct.

🟣 Dexterity: Power and Agility

Type Inference That Helps, Not Hinders

OCaml provides strong typing without the verbose annotations. Its powerful type inference system deduces types for you, letting you focus once again in your domain.

let sum x y = x + y;;
(* val sum : int -> int -> int = <fun> *)
Enter fullscreen mode Exit fullscreen mode

When you make a mistake, the error messages are your friend.

let add_potato x = x + "potato"
(* Error: This expression has type string but an expression was expected of type int *)
Enter fullscreen mode Exit fullscreen mode

You get the benefits of strong typing with the feel of a dynamic language, giving you the agility to refactor and build with confidence.

🟣 Functional: Easy to Reason About

It's very easy to reason about an OCaml program:

Everything is an Expression

In OCaml, almost everything is an expression that returns a value. This includes not just calculations but even conditionals.

(* Definitions are like permanent assignments *)
let num = 3
let sum x y = x + y

(* Even conditionals are expressions that return a value *)
let result = if condition then "this value" else "that value"
Enter fullscreen mode Exit fullscreen mode

Functional to the Core

OCaml encourages a functional style, which leads to more predictable and maintainable code.

  • Immutability by Default: Once a value is defined, it can't be changed. This eliminates a whole class of bugs related to unexpected state changes.

    let pi = 3.1     (* pi is now 3.1 *)
    (* pi = 3.1415  <- This would be an error *)
    let pi = 3.1415  (* This creates a *new* value for pi *)
    
  • Higher-Order Functions: Functions are treated like any other value. You can pass them as arguments, return them from other functions, and store them in data structures.

    (* 'List.fold_left' takes a function as its first argument *)
    let sum lst =
      List.fold_left (fun acc el -> acc + el) 0 lst
    
  • Purity: A pure function's behavior depends only on its inputs. This makes functions easier to reason about, compose, and test because there are no hidden side effects.

🟣 Practical When Need It

While OCaml encourages purity, it's also pragmatic. In situations where controlled mutation can simplify code, OCaml provides a clear and expressive way to handle it, for example allowing to access a reference outside it's normal scope:

let next =
  let counter = ref 0 in
  fun () ->
    incr counter;
    !counter
Enter fullscreen mode Exit fullscreen mode

🟣 What This Might Mean for You

OCaml is, in my opinion, the only language out there that has the right balance between: performance, expressiveness and practicality.


🟣 Why This Matters

OCaml's sweet spot is in high-predictability, high-reliability, and high-performance systems. This is why it's trusted in production by companies in the most demanding fields:

Finance: Jane Street
Developer Tools: Docker
Web Services: Ahrefs
Blockchain: Tezos

The pattern is clear: when failure is not an option, OCaml becomes the option.

But although the previous is true, as in OCaml expressiveness and performance is not an important trade-off we could build more systems in it.


🟣 Let's Explore Together

If any of this sparked your curiosity, I'd love to explore it with you. I'm building small things, writing about my journey, and learning in public.

Let's stay in touch. Let's keep growing.

Thank you.

Top comments (0)