Ela*_*ich 14 c# oop generics ocaml functional-programming
我正在看OCaml的仿函数.它看起来与C++/ C#/中所谓的通用对象完全相同Java.如果您暂时忽略Java的类型擦除,并忽略C++模板的实现细节(我对语言功能感兴趣),仿函数对于泛型非常简洁.如果我理解正确,仿函数会从您提供的类型中为您提供一组新函数,例如
List<MyClass>.GetType() != List<MyOtherClass>.GetType()
Run Code Online (Sandbox Code Playgroud)
但你可以大致重写OCaml的
#module Set =
functor (Elt: ORDERED_TYPE) ->
struct
type element = Elt.t
type set = element list
let empty = []
let rec add x s =
match s with
[] -> [x]
| hd::tl ->
match Elt.compare x hd with
Equal -> s (* x is already in s *)
| Less -> x :: s (* x is smaller than all elements of s *)
| Greater -> hd :: add x tl
let rec member x s =
match s with
[] -> false
| hd::tl ->
match Elt.compare x hd with
Equal -> true (* x belongs to s *)
| Less -> false (* x is smaller than all elements of s *)
| Greater -> member x tl
end;;
Run Code Online (Sandbox Code Playgroud)
成 C#
class Set<T> where T : ISortable
{
private List<T> l = new List<T>();
static public Set<T> empty = new Set<T>();
public bool IsMember(T x) {return l.IndexOf(x) > -1;}
public void Add(T x) {l.Add(x);}
}
Run Code Online (Sandbox Code Playgroud)
当然,由于仿函数会影响a Module(这只是一堆类型的函数和值定义,类似于C#命名空间),因此会略有不同.
但它只是它吗?仿函数仅仅是泛型应用于命名空间吗?或者,我缺少的仿函数和泛型之间是否有任何显着的差异.
即使仿函数只是用于命名空间的泛型,这种方法的显着优势是什么?类也可以用作使用嵌套类的临时命名空间.
但它只是它吗?仿函数仅仅是泛型应用于命名空间吗?
是的,我认为可以将仿函数视为"具有泛型的命名空间",并且在C++中它本身会非常受欢迎,其中唯一的选择是使用具有所有静态成员的类,这很快就变得非常难看.与C++模板相比,一个巨大的优势是模块参数的显式签名(这是我认为C++ 0x概念可以成为的,但是oops).
模块与命名空间完全不同(考虑多个结构签名,抽象和私有类型).
即使仿函数只是用于命名空间的泛型,这种方法的显着优势是什么?类也可以用作使用嵌套类的临时命名空间.
不确定它是否符合重要条件,但可以打开名称空间,同时明确限定类使用.
总而言之 - 我认为单独的仿函数没有明显的"显着优势",它只是代码模块化的不同方法--ML风格 - 它与核心语言非常吻合.不确定将模块系统与语言进行比较是否有意义.
PS C++模板和C#泛型也是完全不同的,因此与它们作为一个整体进行比较感觉有点奇怪.
如果我理解正确,functor 会根据您提供的类型为您提供一组新的函数
更一般地,函子将模块映射到模块。您的Set示例将遵守ORDERED_TYPE签名的模块映射到实现集合的模块。该ORDERED_TYPE签名需要一个类型和比较功能。因此,您的 C# 并不等效,因为它仅通过类型而不是比较函数对集合进行参数化。因此,您的 C# 只能为每个元素类型实现一个集合类型,而函子可以为每个元素模块实现多个集合模块,例如按升序和降序。
即使函子只是命名空间的泛型,这种方法的显着优势是什么?
高阶模块系统的一大优势是能够逐步细化接口。在 OOP 中,一切都是公共的或私有的(或者有时是受保护的或内部的等等)。使用模块,您可以随意逐步细化模块签名,从而提供更多更接近模块内部的公共访问权限,并随着您离该部分代码的进一步深入而抽象出越来越多的内容。我发现这是一个相当大的好处。
与 OOP 相比,高阶模块系统发光的两个例子是相互参数化数据结构实现和构建可扩展的图形库。请参阅Chris Okasaki 博士论文中关于“结构抽象”的部分,以获取参数化其他数据结构的数据结构示例,例如将队列转换为可链接列表的函子。有关使用函子的可扩展和可重用图算法示例,请参阅 OCaml 的优秀 ocamlgraph 库和论文Designing a Generic Graph Library using ML Functors。
类还可以用作使用嵌套类的临时命名空间。
在 C# 中,不能在其他类上参数化类。在 C++ 中,您可以执行一些操作,例如从通过模板传入的类进行继承。
此外,您可以咖喱函子。