пытаюсь повысить типизированность своего движка вывода, и хочу разделить классический Expression на PredicateExpression (в котором есть сравнения ==, < и т.д) и ArithmeticExpression (с +, - и т.д.)., чтобы можно было писать выражения вроде a .+ b .== c, но нельзя было a .== b .< c.
Однако, часть операций над выражениями одинаковые, я их запихиваю в class ExprLike, в итоге получается что-то вроде:
class ExprLike expr where
type SubExpr expr
split :: expr -> Splitted (SubExpr expr) -- ^ разобрать на подвыражения
makeBin :: BinType -> SubExpr expr -> SubExpr expr -> expr
makeUn :: UnType -> SubExpr expr -> expr
ну и
instance ExprLike PredicateExpression where
type SubExpr PredicateExpression = ArithmeticExpression
instance ExprLike ArithmeticExpression where
type SubExpr ArithmeticExpression = ArithmeticExpression
Однако, мне ещё надо, чтобы ещё и SubExpr expr был тоже ExprLike, иначе дальше компилятор в некоторых функциях ругается:
• Could not deduce (ExprLike (SubExpr expr))
arising from a use of ‘exprGenMainLvl1’
Ну ок, пытаюсь сделать так:
class ExprLike expr where
type SubExpr expr :: ExprLike expr => Type
Ну и получаю отлуп:
• Class ‘ExprLike’ cannot be used here
(it is defined and used in the same recursive group)
• In the kind ‘(ExprLike expr) => Type’
|
245 | type SubExpr expr :: (ExprLike expr) => Type
| ^^^^^^^^^^^
Поэтому вопрос -- как то на type family можно наложить ограничение??
Можно в Constraint класса добавить. Я так в bidirectional-instances делал (немножко рекламы, тем более, что вполне возможно в данной задаче что-то такое понадобится)
Обсуждают сегодня