【问题标题】:Is it possible to do a compile time type check on a generic in Rust?是否可以对 Rust 中的泛型进行编译时类型检查?
【发布时间】:2016-12-24 10:10:42
【问题描述】:

我不想检查一个类型是否具有某种特征,但我希望能够区分,例如一个结构和一个整数。由于结构体和整数都可以实现相同的特征,我不知道如何区分它们。

我想这样做的原因是因为我正在使用 serde_json 将泛型类型转换为 JSON,但我希望它成为 JSON Object(当它是struct),但它不应转换为其他任何内容(如 JSON I64)。由于结构体和整数都可以实现 Serialize 特征,因此无法区分它们。

目前,我让进程恐慌,因为它不是可以恢复的错误,但由于我可能在编译时知道这一点,我想知道是否有任何机制可以在编译阶段确定类型。

我想知道如何通过“种类”而不是特征来区分类型。

【问题讨论】:

  • Aochagavia 刚刚向我指出,比较类型并不能解决我的示例中的问题。我仍然希望这个问题能说明问题。我想没有优雅的解决方案,我只需要在运行时进行验证。或者也许可以用程序宏来解决,但这似乎有点过头了。
  • 你需要想出一个方法让编译器检查:“我知道这个序列化的实现总是返回对象”。

标签: types rust


【解决方案1】:

即使您设法在编译时比较了类型,也没有什么能阻止struct 被序列化为Json::I64。它的Serialize 实现可以是任何东西!我能想到一些部分解决方案:

运行时检查

添加运行时检查以通过模式匹配查看结果是否确实是Json::Object。你可以将它与一个断言结合起来,以防你期望它总是正确的。我想这就是你现在正在做的事情。

引入自定义特征

可以创建一个新的特征:

trait SerializeAsObject : Serialize {}

然后您将只为那些您确定将被序列化为对象的数据类型实现。但是,没有什么能阻止您为 i64 实现 trait,因此这里仍有出错的余地。

真正的解决方案:依赖类型

您可能需要一个支持dependent types 的类型系统,以确保数据类型的序列化始终产生给定类型的输出。据我所知,这样的类型系统非常复杂,以至于没有广泛使用的语言支持它(如果您想了解更多信息,可以查看Idris)。

关于编译时检查的思考

虽然编译时检查很棒,但编译器只能做到这一点。以我的经验,在现实世界的编程中使用依赖类型是不值得的。例如,在这种情况下,您需要提供数学证明,以便编译器能够理解 Serialize 的实现总是导致对象的序列化。

即便如此,也无法确保程序没有错误!因此,我认为在这种情况下,正确的做法是使用断言,记录您的函数将在数据无法序列化为对象的情况下发生恐慌,并编写单元测试以确保正确调用它。

【讨论】:

  • 你说得对。因此,“类型检查”结构将不是该示例的正确解决方案。模式匹配需要在运行时完成,这是不幸的。太糟糕了,我需要让进程恐慌一些原则上可以在编译时知道的东西。
  • 有很多在编译时已知的东西都被丢弃了。即使在支持代码推理的语言中,想象一下 程序员 向编译器解释他们的意图是多么困难。这变得非常复杂,非常快。您基本上必须编写编译器能够理解的数学证明。
  • 我同意。在这种情况下,更实用的运行时解决方案应该不是问题。
猜你喜欢
  • 2011-06-15
  • 2015-07-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-08-20
  • 1970-01-01
  • 2018-07-15
  • 1970-01-01
相关资源
最近更新 更多