Вы вводите в заблуждение две очень разные темы (если вы вставили сообщения об ошибках, возможно, они всплыли раньше и получили лучшую обратную связь). Давайте посмотрим на то, что вам было предоставлено - тип данных и классы классов Expr
.
классном Путаница
Вы были обеспечены:
data Expr a = Var Char
| Const a
| (Expr a) :+: (Expr a)
| (Expr a) :*: (Expr a)
| (Expr a) :^: (Expr a)
| (Expr a) :/: (Expr a)
deriving (Show, Eq)
Здесь мы можем увидеть Конструкторы основные арифметические операции. Иными словами, :+:
является конструктором типа Expr a -> Expr a -> Expr a
и аналогичным образом для других.
Теперь вы идете, чтобы попытаться определить функцию, а именно: :+:
class (Num a) => Expr a where
(:+:) :: a -> a -> a
instance Expr a where
x :+: y = x + y
Есть несколько проблем здесь.
- Вы, класс
Expr
, просто называетесь тем же самым, что и вышеуказанный тип, он не имеет отношения к данным, определенным выше.
- Ваш метод
:+:
не является именем юридической функции. Функции, в отличие от конструкторов данных, должны быть допустимыми переменными и, следовательно, не могут начинаться с символов верхнего регистра или двоеточия.
- Экземпляр предназначен для всех типов -
a
является переменной и может соответствовать любому типу. Поэтому вы еще не сказали, что значения x
и y
имеют тип Expr a
.
Я думаю, что вы пытаетесь сделать класс для каждого оператора и сделать экземпляр для каждого конструктора (:+:
,: *: , etc). This is a broken, or at least overly verbose, solution. The only reason to use classes are if there are multiple type that require instances - you only have the one
Expr` типа
Бесклассовой
Там нет необходимости. типа, чтобы решить эту проблему, вместо этого вы можете оценить выражение с помощью традиционной функции, как в удаленном ответе.
Ранее удаленный ответ кажется удаленным с понятием, что и среда привязок для каждого va необходим.Мое чтение проблемы отличается, и я просто оценил бы выражение в простой строке.
evaluate :: Show a => Expr a -> String
evaluate (Var c) = [c]
evaluate (a :+: b) = undefined
evaluate (a :*: b) ... so on and so forth ...
В вышеприведенном вами шаблон соответствует вашим Expr a
для определения операции, то, в зависимости от конкретного случая, вычисляться суб-выражения, как необходимо, прежде чем объединять их в порядке, в зависимости от конструктора (+
с :+:
и т.д.).
'x' и' y' in 'x: +: y' are' Expr a's. Вам действительно нужно реализовать всю упрощающую вещь, например. 'Const a: +: Const b = Const (a + b)' – Ryan
Возможно, вам захочется начать с реализации функции 'оцените :: Fractional a => Expr a -> a'. (Вам понадобится 'Fractional' для деления, все остальное в' Num'.) –
Вам, вероятно, придется реализовать упрощение, используя сопоставление шаблонов 'simp (x: *: (y: /: x ')) | x == x '= y; simp ... 'Упрощение этого выражения« полностью »довольно нетривиально, поэтому я не знаю, какие именно упрощения вы должны выполнять. – user2407038