Я разработчик С#, который работает через "Real World Haskell" , чтобы действительно понимать функциональное программирование, чтобы, когда я узнаю F #, я действительно буду это разбираться, а не просто "писать код С# в F #", так сказать.
Хорошо, сегодня я наткнулся на пример, который, как я думал, я понял 3 раза, только чтобы увидеть то, что я пропустил, обновить мою интерпретацию и рекурсировать (и проклясть тоже, поверьте мне).
Теперь я считаю, что действительно понимаю это, и я написал подробный "английский перевод" ниже. Можете ли вы, гуру Haskell, подтвердить это понимание или указать, что я пропустил?
Примечание. Фрагмент кода Haskell (цитируемый непосредственно из книги) определяет настраиваемый тип, который должен быть изоморфен встроенному типу списка Haskell.
Фрагмент кода Haskell
data List a = Cons a (List a)
| Nil
defining Show
EDIT: после некоторых ответов я вижу одно недоразумение, которое я сделал, но я не совсем понимаю правила "разбора" Хаскелла, которые исправили бы эту ошибку. Поэтому я включил мою оригинальную (неправильную) интерпретацию ниже, а затем исправление, за которым следует вопрос, который до сих пор остается неясным для меня.
EDIT: Вот моя оригинальная (неправильная) "английская интерпретация" фрагмента
- Я определяю тип, называемый "Список".
- Тип списка параметризуется. Он имеет один параметр типа.
- Есть два конструктора значений, которые можно использовать для создания экземпляров списка. Один конструктор значений называется "Nil", а другой конструктор значений называется "Cons" .
- Если вы используете конструктор значения "Nil", то нет полей.
- Конструктор значения "Cons" имеет параметр одного типа.
- Если вы используете конструктор значений "Минус" , есть два поля, которые должны быть предоставлены. Первым обязательным полем является экземпляр List. Второе обязательное поле является экземпляром a.
- (Я намеренно пропустил что-либо о "определении Show", потому что это не часть того, что я хочу сосредоточить прямо сейчас).
Исправленная интерпретация будет следующей (изменения в BOLD)
- Я определяю тип, называемый "Список".
- Тип списка параметризуется. Это имеет параметр одного типа.
- Есть два конструктора значений которые могут быть использованы для создания экземпляров списка. Один конструктор значений "Nil" и другое значение конструктор называется "Минусы".
-
Если вы используете конструктор значения "Nil", то нет полей.
5. (эта строка была удалена... это не точно) Конструктор значения "Минус" имеет один параметр типа.
-
Если вы используете конструктор значения "Cons" , есть 2 поля которые должны быть предоставлены. Первый обязательное поле является экземпляром a. Второе обязательное поле - это экземпляр "List-of-a".
- (Я намеренно пропустил что-либо о "определении Show", потому что это не часть того, что я хочу сосредоточить прямо сейчас).
Вопрос, который остается неясным
Первоначальная путаница заключалась в части фрагмента, который читает "Cons a (List a)". На самом деле, это та часть, которая до сих пор не ясна для меня.
Люди указали, что каждый элемент в строке после токена "Минус" - это тип, а не значение. Таким образом, это означает, что эта строка говорит: "Конструктор значения Cons имеет 2 поля: один из типов" a ", а другой тип" list-of-a "."
Это очень полезно знать. Однако что-то еще неясно. Когда я создаю экземпляры с использованием конструктора Cons Cons, эти экземпляры "интерпретируют" первый "a" как значение "помещают значение, переданное здесь". Но они не интерпретируют второй "а" таким же образом.
Например, рассмотрим этот сеанс GHCI:
*Main> Cons 0 Nil
Cons 0 Nil
*Main> Cons 1 it
Cons 1 (Cons 0 Nil)
*Main>
Когда я печатаю "Cons 0 Nil", он использует конструктор значения "Cons" для создания экземпляра List. Начиная с 0, он узнает, что параметр типа "Integer". Пока нет путаницы.
Однако он также определяет, что значение первого поля Cons составляет 0. Но он ничего не определяет о значении второго поля... он определяет только, что второе поле имеет тип "Integer List",.
Итак, мой вопрос: почему "а" в первом поле означает "тип этого поля:" а ", а значение этого поля" а ", а" а "во втором поле означает только" Тип этого поля - "Список a"?
EDIT: Я считаю, что теперь я видел свет, благодаря нескольким ответам. Позвольте мне сформулировать это здесь. (И если каким-то образом это по-прежнему некорректно, пожалуйста, дайте мне знать!)
В фрагменте "Cons a (List a)" мы говорим, что конструктор значения "Cons" имеет два поля и первое поле имеет тип "a" и второе поле имеет тип "a" , Список '.
Это все, что мы говорим! В частности, мы говорим НИЧЕГО о значениях! Это ключевой момент, который мне не хватало.
Позже мы хотим создать экземпляр, используя конструктор значения "Cons" . Мы вводим это в интерпретатор: "Минусы 0 Нил". Этот явно сообщает конструктору Cons Cons использовать 0 для значения первого поля и использовать Nil как значение для второго поля.
И все это к нему. Как только вы знаете, что определение конструктора значения указывает только на типы, все становится ясным.
Спасибо всем за полезные ответы. И, как я сказал, если что-то еще не работает, пожалуйста, непременно расскажите мне об этом. Спасибо.