Подтвердить что ты не робот

Почему в конструкторе типов в Haskell существует конструктор значений?

Я новичок в Haskell и в настоящее время перехожу через Real World Haskell. В книге говорится, что конструктор типов используется только в сигнатуре типа, в то время как конструктор значений используется в фактическом коде. Он также дает пример объявления, показывающего, что имена для обоих не зависят друг от друга. Почему в первую очередь нужны два конструктора, если только один из них используется в реальном коде? Поскольку мы не будем использовать конструктор типа в фактическом коде, какая цель выполняет конструктор типа?

4b9b3361

Ответ 1

Возможно, имена немного вводят в заблуждение. Конструктор типа представляет имя типа, который вы объявляете. Они называются так, потому что они строят типы, а не значения: действительно, будучи (возможно) параметризованными по переменным типа, они определяют семейство типов. Они действуют как С++-шаблоны и Java-дженерики. В data MyType a b = Constr a b MyType является конструктором типа, который принимает два типа a и b для создания нового типа (MyType a b).

Конструктор значений - это единственная часть, которую вы бы назвали "конструктором" на других (объектно-ориентированных) языках, потому что вам нужно, чтобы строить значения для этого типа. Итак, в предыдущем примере, если вы берете конструктор значений Constr :: a -> b -> MyType a b, вы можете создать значение Constr "abc" 'd' :: MyType [Char] Char.

Ответ 2

Это немного похоже на высказывание "зачем нам нужны классы и объекты, если объекты - это единственное, что действительно работает?"

Два типа конструкторов выполняют разные задания. Конструкторы типов входят в сигнатуры типов. Конструкторы значений входят в исполняемый код.

В простейшем случае тип "конструктор" - это просто имя типа. В простейшем случае тип имеет только один конструктор значений. Таким образом, вы получаете такие вещи, как

data Point = Point Int Int

Вы можете сказать себе: "Почему, черт возьми, мне нужно дважды писать Point?"

Но теперь рассмотрим менее тривиальный пример:

data Tree x = Leaf x | Branch (Tree x) (Tree x)

Здесь Tree - конструктор типа. Вы даете ему аргумент типа, и он "конструирует" тип. Итак, Tree Int - это один тип, Tree String - другой тип и т.д. (Подобно шаблонам на С++ или дженерикам в Java или Eiffel.)

С другой стороны, Leaf является конструктором значений. Учитывая значение, он выдает дерево из дерева" > w630 > . Таким образом, Leaf 5 является значением Tree Int, Leaf "banana" является значением Tree String и т.д.

Аналогично для Branch. Он принимает два значения дерева и создает дерево node с этими деревьями как дочерние. Например, Branch (Leaf 2) (Leaf 7) - это значение Tree Int.

Ответ 3

Один удобный способ получить интуицию о типах и значениях состоит в том, что первые значения время компиляции, а последние - время выполнения. Другими словами, конструкторы Type являются конструкторами значений в наборе типов Haskell, с единственной целью набирать вашу программу во время компиляции. Это также означает, что вы не можете создать тип во время выполнения, и вы не можете построить значение во время компиляции.

Итак, поскольку вы не можете явным образом входить во время выполнения на основе значения типа (хотя вы можете неявно с помощью typeclasses), конструкторы Type полностью бесполезны в качестве объектов времени выполнения и во многих случаях полностью отсутствуют в окончательный двоичный код. И наоборот, поскольку конструкторы значений позволяют создавать значения в наборе своего типа во время выполнения, они абсолютно бесполезны как объект времени компиляции.

Из-за этого простого свойства конструкторы Type и конструкторы Value могут однозначно делиться именами.