Проблема
Рассмотрим следующую проблему проектирования в Haskell. У меня есть простой символьный c EDSL, в котором я хочу express переменных и общих выражений (многомерных полиномов), таких как x^2 * y + 2*z + 1
. Кроме того, я хочу express определенных символов c уравнений над выражениями, скажем x^2 + 1 = 1
, а также определений , например, x := 2*y - 2
.
Цель состоит в том, чтобы:
- Имеет отдельный тип для переменных и общих выражений - некоторые функции могут применяться к переменным, а не к сложным выражениям. Например, оператор Definition
:=
может иметь тип (:=) :: Variable -> Expression -> Definition
, и не должно быть возможности передать сложное выражение в качестве его левого параметра (хотя должно ). можно передать переменную в качестве ее правого параметра без явного приведения ). - иметь выражения с экземпляром
Num
, чтобы можно было добавлять целые литералы в выражения и использовать удобную запись для общих алгебраических c операций, таких как сложение или умножение, без введения некоторых вспомогательных операторов-оберток.
Другими словами, я хотел бы иметь неявное и stati c приведение типа (приведение) переменных к выражениям. Теперь я знаю, что в Haskell нет неявных приведений типов. Тем не менее, определенные концепции объектно-ориентированного программирования (в данном случае простое наследование) являются выразимыми в системе типов Haskell, с расширениями языка или без них. Как я могу удовлетворить оба вышеупомянутых пункта, сохраняя легкий синтаксис? Это вообще возможно?
Обсуждение
Понятно, что основная проблема здесь - ограничение типа Num
, например,
(+) :: Num a => a -> a -> a
В принципе, можно написать один (обобщенный) алгебраический тип данных c для переменных и выражений. Тогда можно было бы написать :=
таким образом, чтобы выражение левой части распознавалось, и принимался только конструктор переменной, в противном случае - ошибка времени выполнения. Это, однако, не чистое, stati c (то есть время компиляции) решение *
Пример
В идеале я хотел бы получить легкий синтаксис, такой как
computation = do
x <- variable
t <- variable
t |:=| x^2 - 1
solve (t |==| 0)
В частности, я хочу запретить нотацию, такую как t + 1 |:=| x^2 - 1
, поскольку :=
должно давать определение переменной, а не целое выражение в левой части.