# Peculiar Ocamllex error

**URL:** <https://discuss.ocaml.org/t/peculiar-ocamllex-error/16584>\
**Category:** Learning\
**Created:** [April 30, 2025, 4:12pm UTC](https://discuss.ocaml.org/t/peculiar-ocamllex-error/16584 "2025-04-30T16:12:37Z")\
**Posts on this page:** 3\
**Page:** 1

<div class="post-metadata">

**Author:** ![HumamAlhusaini](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/humamalhusaini/32/5957_2.png) [@HumamAlhusaini](https://discuss.ocaml.org/u/HumamAlhusaini)\
**Post date:** [April 30, 2025, 4:12pm UTC](https://discuss.ocaml.org/t/peculiar-ocamllex-error/16584/1 "2025-04-30T16:12:37Z")

</div>

I made this [repository](https://github.com/HumamAlhusaini/reproduced-error) to reproduce the error in only 111 lines of code.

This is the error

```auto
File "lexer.mll", line 33, characters 25-33:
Error: This variant expression is expected to have type unit
       There is no constructor CONSTANT within type unit
make: *** [Makefile:39: lexer.cmo] Error 2

```

My first assumption was that it had to do with the fact that the type of the CONSTANT token is `%token <Ast.constant> CONSTANT`. However, when I change it to something else like `%token <string> CONSTANT`, it returns the same error. So I believe this has something to do with the Ocamllex.  
This is the parser simplified.

```auto
let int = '-'? digit+ (* regex for integers *)
let whitespace = [' ' '\t']+
let newline = '\r' | '\n' | "\r\n"

rule read_token = parse
  | whitespace { read_token lexbuf }
  | newline { next_line lexbuf; }
  | int as i { CONSTANT (CONST_INT i) }
  | "+" { ADD }
  | "-" { SUB }
  | "*" { MULT }
  | "/" { DIV }

```

I decided to make it more explicit, so I replaced `{ CONSTANT (CONST_INT i) }` with  
`{ Parser.CONSTANT (CONST_INT i) }`, which gave me a more informative error

```auto
File "lexer.mll", line 33, characters 25-40:
 Error: The constructor Parser.CONSTANT belongs to the variant type
          Parser.token
       but a constructor was expected belonging to the variant type unit
make: *** [Makefile:39: lexer.cmo] Error 2

```

The same thing happens with the other tokens like ADD and SUB. So I decided to try and fix this error by changing `%token <Ast.constant> CONSTANT` to `%token <unit> CONSTANT`, however, that still gave me the same exact error.

So just as a guess, I changed `{ CONSTANT (CONST_INT i) }` to `{ Ast.CONSTANT ( CONST_INT i) }`, which obviously did not work

---

<div class="post-metadata">

**Author:** ![JohnJ](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/johnj/32/6020_2.png) [@JohnJ](https://discuss.ocaml.org/u/JohnJ)\
**Post date:** [April 30, 2025, 4:32pm UTC](https://discuss.ocaml.org/t/peculiar-ocamllex-error/16584/2 "2025-04-30T16:32:34Z")

</div>

> [@HumamAlhusaini](#):
>
> ```auto
> Error: This variant expression is expected to have type unit
> There is no constructor CONSTANT within type unit
> 
> ```

The first question to ask is, why is does the type-checker expect the expression to have type `unit`? There must be something in `read_token` which returns that type.

From looking at the full code in the repository, it seems like the `next_line` function returns type `unit`. So now we can see the type error more clearly here:

> [@HumamAlhusaini](#):
>
> ```auto
> | newline { next_line lexbuf; } (* Returns unit *)
> | int as i { CONSTANT (CONST_INT i) } (* Returns token *)
> 
> ```

You likely need to write `{ next_line lexbuf; read_token lexbuf }`.

---

<div class="post-metadata">

**Author:** ![HumamAlhusaini](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/humamalhusaini/32/5957_2.png) [@HumamAlhusaini](https://discuss.ocaml.org/u/HumamAlhusaini)\
**Post date:** [April 30, 2025, 4:36pm UTC](https://discuss.ocaml.org/t/peculiar-ocamllex-error/16584/3 "2025-04-30T16:36:12Z")

</div>

Thanks, now that seems really obvious
