Вложенный алгебраический тип данных Haskell

Я пытаюсь смоделировать следующий простой Scala ADT в Haskell:

sealed trait Value

sealed trait Literal < Value
case object Null extends Literal
case class IntLiteral(value: Int) extends Literal

case class Variable(name: String) < Value

Я моделирую черту Literal:

Prelude> data Literal = Null | IntLiteral Int deriving (Show, Eq)

Все идет нормально:

Prelude> Null
Null
Prelude> Null == IntLiteral 3
False
Prelude> IntLiteral 3 == IntLiteral 3
True

Теперь я пытаюсь представить Variable:

data Value = Literal | Variable String deriving (Show, Eq)

Почему это не работает?

Prelude> Null == Variable "foo"

<interactive>:3:9: error:
    • Couldn't match expected type ‘Literal’ with actual type ‘Value’
    • In the second argument of ‘(==)’, namely ‘Variable "foo"’
      In the expression: Null == Variable "foo"
      In an equation for ‘it’: it = Null == Variable "foo"

person Bob T    schedule 08.07.2017    source источник
comment
value Literal является конструктором типа Value; он не принимает аргументов и не связан с типом Literal. Вы имели в виду data Value = Literal Literal | ... Literal Null == Variable "foo"?   -  person melpomene    schedule 08.07.2017
comment
Если я использую data Value = Literal Literal | Variable String deriving (Show, Eq), я получаю ожидаемый результат: (Literal $ IntLiteral 3) == Variable "foo" => False. Я не уверен, что понимаю разницу между конструктором Literal и типом Literal.   -  person Bob T    schedule 08.07.2017
comment
Первое слово после data .. = и после каждого последующего | является именем конструктора (значение). Остальные относятся к типам. Синтаксис примерно такой: data T .. = K1 T11 T12 ... | K2 T21 T22 ... | K3 T31 T32 ...| ...   -  person chi    schedule 08.07.2017
comment
Null относится к типу Literal, Variable "foo" относится к типу Value. также может быть конструктор данных Literal, не связанный с одноименным типом. это просто разные вещи, живущие в разных пространствах имен в Haskell. если вы пишете data Value = Literal Literal | ..., первое Literal — это имя конструктора данных (в этом случае создает значения типа Value), второе — это имя типа.   -  person Will Ness    schedule 08.07.2017
comment
Почему за это проголосовали? Это выглядит как совершенно правильный и резонный вопрос.   -  person Paul Johnson    schedule 08.07.2017
comment
Спасибо, это имеет смысл. Я был бы рад отметить один из них как принятый ответ.   -  person Bob T    schedule 08.07.2017


Ответы (1)


Null относится к типу Literal, Variable "foo" относится к типу Value. Также может быть конструктор данных Literal, не связанный с одноименным типом. Это просто разные вещи, живущие в разных пространствах имен в Haskell. Если вы пишете

data Value = Literal Literal | ...

затем первое Literal — это имя конструктора данных (в этом случае создает значения типа Value), второе — имя типа.

person Will Ness    schedule 09.07.2017