naa*_*ing 11
HigherLogics是我的博客,我花了很多时间来研究这个问题.这种限制确实是对类型构造函数的抽象,即"泛型泛型".模仿ML模块和仿函数似乎是最好的,至少需要一个(半安全)模型.
它主要归结为定义抽象类型,以及对应于在该类型上运行的模块签名的接口.抽象类型和界面共享一个类型参数B,我称之为"品牌"; 品牌通常只是实现模块接口的子类型.该品牌确保传入的类型是模块所期望的正确子类型.
// signature
abstract class Exp<T, B> where B : ISymantics<B> { }
interface ISymantics<B> where B : ISymantics<B>
{
Exp<int, B> Int(int i);
Exp<int, B> Add(Exp<int, B> left, Exp<int, B> right);
}
// implementation
sealed class InterpreterExp<T> : Exp<T, Interpreter>
{
internal T value;
}
sealed class Interpreter : ISymantics<Interpreter>
{
Exp<int, Interpreter> Int(int i) { return new InterpreterExp<int> { value = i }; }
Exp<int, Interpreter> Add(Exp<int, Interpreter> left, Exp<int, Interpreter> right)
{
var l = left as InterpreterExp<int>; //semi-safe cast
var r = right as InterpreterExp<int>;//semi-safe cast
return new InterpreterExp<int> { value = l.value + r.value; }; }
}
}
Run Code Online (Sandbox Code Playgroud)
如您所见,演员表大多是安全的,因为类型系统确保表达式类型的品牌与解释器的品牌相匹配.解决这个问题的唯一方法是,如果客户创建自己的Exp类并指定Interpreter品牌.有一个更安全的编码可以避免这个问题,但它对于普通的编程来说太笨重了.
我后来使用这种编码并将 Oleg的一篇用MetaOCaml编写的论文中的例子翻译成了C#和Linq.解释器可以透明地运行在ASP.NET或客户端使用此嵌入式语言服务器端编写的程序作为JavaScript.
这种对解释器的抽象是Oleg最终无标记编码的一个特征.博客文章中提供了他论文的链接.
接口在.NET中是一流的,因为我们使用接口来编码模块签名,所以模块和模块签名在这种编码中也是一流的.因此,仿函数只是直接使用接口代替模块签名,即.他们会接受一个ISymantics <B>的实例并委托任何调用它.
我不太清楚ML仿函数真的能回答你的问题.但我会说.我总是发现使用monadic编程的一个限制因素是无法在"forall M. 某种类型表达式与M <T> " 的意义上抽象"M "(例如,其中M是一种类型)构造函数(带有一个或多个泛型参数的类型)).所以,如果这是你有时需要/用仿函数使用的东西的话,我觉得非常有信心有表达它的.Net没有什么好办法.
ML模块的一个关键特性是共享规范..NET中没有能够模仿它们的机制 - 所需的机制就是太不同了.
您可以尝试通过将共享类型转换为参数来执行此操作,但这不能忠实地模拟定义签名的能力,然后可能以多种不同方式应用共享.
在我看来,.NET将从拥有这种机制的东西中受益 - 它将更接近于真正支持现代语言的多样性.希望包括模块系统的最新进展,如MixML中的模块系统,我认为模块系统的未来. http://www.mpi-sws.org/~rossberg/mixml/