如何使用存在类型的异质列表获得表达问题的可扩展性
我正在尝试做的事情,
我正在尝试解决与Haskell中表达问题相似的问题。
它们有不同的表达方式和不同的操作。表达式和操作都应可扩展。
我的尝试:
为表达式创建一个类型类,并为每个操作创建类型类。
可以通过声明表达式类型类的实例以及所有受支持的操作类型类的实例来完成添加新类型的表达式。
可以通过创建新类型类并为所有应支持该操作的表达式类型声明一个实例来完成添加新操作。
class Expr a
class (Expr a) => PrettyPrint a where
prettyPrint :: a -> String
class (Expr a) => Evaluate a where
evaluate :: a -> Int
一些示例(并不重要):
newtype Literal = Literal Int
instance Expr Literal
data Add l r = Add l r
instance (Expr l, Expr r) => Expr (Add l r)
instance PrettyPrint Literal where
prettyPrint (Literal x) = show x
instance Evaluate Literal where
evaluate (Literal x) = x
instance (PrettyPrint l, PrettyPrint r) => PrettyPrint (Add l r) where
prettyPrint (Add left right) = "(" ++ prettyPrint left ++ " + " ++ prettyPrint right ++ ")"
instance (Evaluate l, Evaluate r) => Evaluate (Add l r) where
evaluate (Add left right) = evaluate left + evaluate right
现在我需要一个支持所有操作的表达式的异质列表。这可以在所有这些表达式类型上使用存在类型作为包装器来完成。
data SomeExpr = forall a. (Expr a, PrettyPrint a, Evaluate a) => SomeExpr a
instance Expr SomeExpr
instance PrettyPrint SomeExpr where
prettyPrint (SomeExpr x) = prettyPrint x
instance Evaluate SomeExpr where
evaluate (SomeExpr x) = evaluate x
但是现在我失去了操作的可扩展性,因为需要添加新操作作为某种定义的构造。为了使SomeEXPR提供所有操作,所有操作都必须作为约束。
是否有一种方法可以具有表达式和操作的可扩展性的表达式列表?
也应该有可能在不知道编译时表达式的确切类型的情况下创建异类列表。
edit :具有可扩展性,是指定义新型表达式(例如字面
和添加l r
),以及对表达式的新操作(例如<<<<<代码> PrettyPrint 和在其他模块中评估
)。
What I'm trying to do
I'm trying to solve a problem similar to the Expression Problem in haskell.
There are different expressions and different operations for them. Both expressions and operations should be extensible.
My attempt:
Create a type class for expressions and a type class for each operation.
Adding new types of expressions can be done by declaring an instance of the expression type class and also an instance for all supported operation type classes.
Adding a new operation can be done by creating a new type class and declare an instance of it for all expression types that should support that operation.
class Expr a
class (Expr a) => PrettyPrint a where
prettyPrint :: a -> String
class (Expr a) => Evaluate a where
evaluate :: a -> Int
Some examples (not that important):
newtype Literal = Literal Int
instance Expr Literal
data Add l r = Add l r
instance (Expr l, Expr r) => Expr (Add l r)
instance PrettyPrint Literal where
prettyPrint (Literal x) = show x
instance Evaluate Literal where
evaluate (Literal x) = x
instance (PrettyPrint l, PrettyPrint r) => PrettyPrint (Add l r) where
prettyPrint (Add left right) = "(" ++ prettyPrint left ++ " + " ++ prettyPrint right ++ ")"
instance (Evaluate l, Evaluate r) => Evaluate (Add l r) where
evaluate (Add left right) = evaluate left + evaluate right
Now I need a heterogeneous list of expressions that support all operations. This can be done with an existential type as a wrapper over all these expression types.
data SomeExpr = forall a. (Expr a, PrettyPrint a, Evaluate a) => SomeExpr a
instance Expr SomeExpr
instance PrettyPrint SomeExpr where
prettyPrint (SomeExpr x) = prettyPrint x
instance Evaluate SomeExpr where
evaluate (SomeExpr x) = evaluate x
But now I've lost the extensibility of operations because a new operation would need to be added as a constaint to definition of SomeExpr. In order for SomeExpr to provide all operations, all operations must be given as constraints.
Is there a way to have a heterogeneous list of expressions while still having extensibility of both expression types and operations?
It should also be possible to create the heterogeneous list without knowing the exact types of the expressions at compile time.
Edit: With extensibility I mean defining new types of expressions (like Literal
and Add l r
), as well as new operations on expressions (like prettyPrint
and evaluate
) in other modules.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论