David smith
David smith

Reputation: 21

How to fix Ocaml Unbound constructor error

I am brand new to OCaml. I am trying to write this basic recursive function called H sequence. Here is my code:

let rec H n = 
    if n == 0 then
        0
    else 
       n - H(H(H(n - 1)))
;;


print_int(H 3);

I am pretty sure my function H is correct However I get this error:

File "main.ml", line 1, characters 8-9:
Error: Unbound constructor H

I am not sure how and what to bind to H. If anyone can give me some advice it would be much appreciated. If it helps I am using this website to run my code: https://www.tutorialspoint.com/compile_ocaml_online.php

Upvotes: 1

Views: 8083

Answers (1)

octachron
octachron

Reputation: 18892

In Ocaml, the first character of an identifier is used to determine its syntactical class. In particular,

  • variables
  • types
  • record fields
  • classes
  • classes types
  • instance variables

must start with a lowercase letter. Contrarily

  • constructors
  • modules

must start with an uppercase letter. (They are 5 exceptions for constructors [], (), (::), true and false). And

  • modules types
  • polymorphic variant constructors

may start with a lowercase or uppercase letter. However, it is more idiomatic to use an uppercase for them.

So if you are defining

let rec H n = 
    if n == 0 then
        0
    else 
       n - H(H(H(n - 1)))

the compiler reads H as a constructor, and thus it thinks that you are trying to define a variable in a way similar to

type t = C of int
let (C n) = C 1

In other words, the solution to your problem is to rename your variable h:

let rec h n = 
    if n = 0 then
        0
    else 
       n - h(h(h(n - 1)))

(Don't use == on non-mutable variable in OCaml).

If you are wondering why there is such a distinction between Constructors and variables, one of the main reason is that otherwise it becomes possible to write some very confusing pattern matching. Consider for instance

type t =
| X
| Y
| Z

let f x = match x with
| X -> 0
| y -> 1

in the first branch of the pattern matching

| X -> 0

we are checking if x is the constructor X. However, in the second branch,

| y -> 1

we are renaming the variable x to y in the branch. Here, we can use the case of the first character to know in which cases we are. Without this syntactical distinction, we will need to remember if there were a constructor X or y in scope during the pattern matching.

Upvotes: 2

Related Questions