可以ML仿函数与.NET接口和泛型被实际表现? 是否有违抗这种编码先进的ML仿函数使用的例子吗?
答案汇总 :
在一般情况下,答案是否定的。 ML模块提供的功能(诸如经由签名规范共享[ 1 ]),其不直接映射到.NET概念。
然而,对于某些使用情况的ML成语可以翻译。 这些情况包括不仅基本Set
算符[ 2 ],也单子[的函子编码3 ],和甚至更高级的Haskell的用途,如最后无代码解释器[ 4 , 5 ]。
实用的编码需要妥协,如半安全向下转换。 您的里程将持谨慎态度。
博客和代码:
- blog.matthewdoig.com
- higherlogics.blogspot.com
- 单子算符,F#
其中之一的ML模块的主要功能是分享规范。 有没有在.NET中没有机制,能够模拟它们 - 所需的机器是太不同。
您可以尝试通过关闭共享类型分为参数做到这一点,但这并不能如实地模仿定义签名的能力,然后再应用共享,也许在多种不同的方式。
在我看来,.NET将受益于东西,确实有这样的机器 - 那就更接近真正支持现代语言的多样性。 希望包括模块的系统像那些在MixML,这在我看来是模块系统的未来更多的最新进展。 http://www.mpi-sws.org/~rossberg/mixml/
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; }; }
}
}
正如你所看到的,演员大多是安全的,因为该类型系统保证了品牌的表达式类型的品牌诠释者相匹配。 要搞砸的唯一方法,就是如果客户端创建了自己的精通等级和指定解释品牌。 有这太避免这一问题的安全编码,但它远远普通程序太烦琐。
后来我用这个编码和翻译的例子从写在MetaOCaml奥列格的一篇论文中,使用C#和LINQ。 解释器可以透明地运行在ASP.NET中使用该语言的嵌入式服务器端或客户端如JavaScript编写的程序。
这种抽象了口译是Oleg的最终无标签编码的功能。 在博客文章中提供链接到他的论文。
接口在.NET一流的,因为我们使用的接口编码模块签名,模块和模块的签名也是这个编码一流。 因此,简单地函子来代替模块签名,即直接使用的接口。 他们将接受ISymantics <B>的一个实例,并委派给它的任何呼叫。
我不知道ML仿函数足够好,真正回答你的问题。 但是,我会说我总是与一元编程找到的.Net的一个限制因素是不能在抽象“M”中的意义上的“的forall M. 具有M某种类型的表达<T>”(例如,其中M是一种类型的构造函数(类型需要一个或多个通用参数))。 所以,如果这是你有时需要/用仿函数使用的东西的话,我觉得非常有信心有表达它的.Net没有什么好办法。
我现在已经发布了详细的描述我的翻译ML模块,签名和函子的一个等价的C#编码。 我希望有人发现它是有用的。
Brian的评论是即期。 下面是一个使用仿函数,得到(严格)实现的Haskell OCaml的代码sequence :: (Monad m) => [ma] -> m [a]
参数化对有关单子:
module type Monad =
sig
type 'a t (*'*)
val map : ('a -> 'b) -> ('a t -> 'b t)
val return : 'a -> 'a t
val bind : 'a t -> ('a -> 'b t) -> 'b t
end
module type MonadUtils =
sig
type 'a t (*'*)
val sequence : ('a t) list -> ('a list) t
end
module MakeMonad (M : Monad) : MonadUtils =
struct
type 'a t = 'a M.t
let rec sequence = function
| [] ->
M.return []
| x :: xs ->
let f x =
M.map (fun xs -> x :: xs) (sequence xs)
in
M.bind x f
end
这看起来具有挑战性的.NET来表达。
更新 :
通过使用技术naasking
我能够编码可重复使用的sequence
在F#功能的主要类型安全的方式(采用向下转换)。
http://gist.github.com/192353