Приведение типов при работе с вложенными структурами данных

У меня определены следующие структуры данных:

data Operator = Plus | Times | Minus deriving (Eq,Show)
data Variable = A | B | C deriving (Eq,Show)
newtype Const = D Numeral deriving (Eq,Show)
data CVO = Const | Variable | Operator deriving (Eq,Show)
type Expr = [CVO]

Я определил следующую функцию:

eval2 :: Expr -> Integer
eval2 x = helper x

Я хотел бы проверить, является ли элемент списка CVO (Expr) экземпляром Const, Variable или Operator (это работает), и я хотел бы реализовать меняющийся код для определенного типа экземпляра (например, Plus, Times, Минус за оператора).

helper :: Expr -> Integer
helper [] = 2
helper (x:xs) 
    | x == Operator && x == Plus = 1

Я не могу сравнивать x с Plus, потому что он ожидает, что x будет типа CVO.

Couldn't match expected type ‘CVO’ with actual type ‘Operator’

Можно ли каким-то образом привести x к экземпляру Operator, чтобы выполнить сравнение?


person Alexander    schedule 25.11.2016    source источник


Ответы (1)


Значение не может иметь два разных типа одновременно. Если x является CVO, вы не можете использовать == для сравнения с Plus, который является Operator.

На данный момент тип CVO состоит из трех постоянных значений, называемых Const, Variable и Operator. Я предполагаю, что вы действительно хотели, чтобы он содержал значения типа Const, Variable или Operator. Вы делаете это, объявляя аргументы конструкторам.

data CVO = Const Const  -- a constructor whose name is Const and contains a value of type Const
         | Var Variable  -- a constructor named Var containing a Variable
         | Op Operator  -- a constructor named Op containing an Operator

Заданное значение типа CVO должно быть создано из одного из этих трех конструкторов, содержащих значение правильного типа. Вы можете проверить, какой конструктор использовался для создания CVO, и одновременно распаковать значение, используя сопоставление с образцом. Что-то вроде этого:

helper :: Expr -> Integer
helper [] = 0
helper (Op o:xs)  -- because we matched Op, we know o :: Operator
    | o == Plus = 1
    | otherwise = 2
helper _ = 3
person Benjamin Hodgson♦    schedule 25.11.2016
comment
Спасибо! Это имеет смысл. - person Alexander; 25.11.2016