Как исправить ошибку конструктора Ocaml Unbound - PullRequest
0 голосов
/ 03 мая 2020

Я новичок в OCaml. Я пытаюсь написать эту базовую c рекурсивную функцию под названием H sequence. Вот мой код:

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


print_int(H 3);

Я почти уверен, что моя функция H верна. Однако я получаю эту ошибку:

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

Я не уверен, как и что связать с H. Если кто-нибудь может дать мне несколько советов, это будет высоко ценится. Если это поможет, я использую этот сайт для запуска моего кода: https://www.tutorialspoint.com/compile_ocaml_online.php

1 Ответ

1 голос
/ 04 мая 2020

В Ocaml первый символ идентификатора используется для определения его синтаксического класса. В частности,

  • переменные
  • типы
  • поля записи
  • классы
  • типы классов
  • экземпляр переменные

должны начинаться со строчной буквы. Напротив,

  • конструкторы
  • модули

должны начинаться с заглавной буквы. (Это 5 исключений для конструкторов [], (), (::), true и false). И

  • типы модулей
  • polymorphi c варианты конструкторов

могут начинаться со строчной или прописной буквы. Однако более логично c использовать для них заглавные буквы.

Так что если вы определяете

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

, то компилятор читает H как конструктор, и поэтому он думает, что что вы пытаетесь определить переменную аналогично

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

Другими словами, решение вашей проблемы - переименовать вашу переменную h:

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

( Не используйте == для не изменяемой переменной в OCaml.

Если вам интересно, почему существует такое различие между Конструкторами и переменными, одна из основных причин заключается в том, что в противном случае становится возможным написать какое-то очень запутанное сопоставление с образцом. Рассмотрим, например,

type t =
| X
| Y
| Z

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

в первой ветви сопоставления с шаблоном

| X -> 0

, мы проверяем, является ли x конструктором X. Однако во второй ветви,

| y -> 1

мы переименовываем переменную x в y в ветви. Здесь мы можем использовать регистр первого символа, чтобы узнать, в каких случаях мы находимся. Без этого синтаксического различия нам нужно будет помнить, был ли конструктор X или y в области видимости во время сопоставления с образцом.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...