您能向我解释OCaml函子吗? [英] Would you please explain OCaml functors to me?

查看:94
本文介绍了您能向我解释OCaml函子吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

可能重复:
在函数式编程中,什么是函子?

Possible Duplicate:
In Functional Programming, what is a functor?

我对OCaml不太了解,我已经学习F#一段时间了,并且对它有所了解.

I don't know much about OCaml, I've studied F# for some time and quite understand it.

他们说F#缺少OCaml中存在的函子模型.我试图弄清楚到底是什么函子,但是维基百科和教程对我没有多大帮助.

They say that F# misses functor model, which is present in OCaml. I've tried to figure out what exactly functor is, but wikipedia and tutorials didn't help me much.

你能为我阐明这个谜团吗?在此先感谢:)

Could you please illuminate that mystery for me? Thanks in advance :)

我明白了这一点,对所有帮助过我的人都表示感谢.您可以将问题作为以下项目的重复项来结束:在函数式编程"中,什么是函子?

I've caught the point, thx to everyone who helped me. You can close the question as exact duplicate of: In Functional Programming, what is a functor?

推荐答案

如果您来自OOP Universe,那么将模块视为类似于静态类可能会有所帮助.与.NET静态类相似,OCaml模块具有构造函数.与.NET不同,OCaml模块可以在其构造函数中接受参数.函子是您传递给模块构造函数的对象的冠冕堂皇的名字.

If you come from an OOP universe, then it probably helps to think of a module as analogous to a static class. Similar to .NET static classes, OCaml module have constructors; unlike .NET, OCaml modules can accept parameters in their constructors. A functor is a scary sounding name for the object you pass into the module constructor.

因此,使用二叉树的规范示例,我们通常将其用F#编写,如下所示:

So using the canonical example of a binary tree, we'd normally write it in F# like this:

type 'a tree =
    | Nil
    | Node of 'a tree * 'a * 'a tree

module Tree =
    let rec insert v = function
        | Nil -> Node(Nil, v, Nil)
        | Node(l, x, r) ->
            if v < x then Node(insert v l, x, r)
            elif v > x then Node(l, x, insert v r)
            else Node(l, x, r)

好,花花公子.但是F#如何知道如何使用<>运算符比较两个'a类型的对象?

Fine and dandy. But how does F# know how to compare two objects of type 'a using the < and > operators?

在幕后,它的动作是这样的:

Behind the scenes, its doing something like this:

> let gt x y = x > y;;

val gt : 'a -> 'a -> bool when 'a : comparison

好吧,如果您有一个类型为Person的对象,该对象没有实现该特定接口怎么办?如果要动态定义排序功能怎么办?一种方法就是按如下方式传递比较器:

Alright, well what if you have an object of type Person which doesn't implement that particular interface? What if you wanted to define the sorting function on the fly? One approach is just to pass in the comparer as follows:

    let rec insert comparer v = function
        | Nil -> Node(Nil, v, Nil)
        | Node(l, x, r) ->
            if comparer v x = 1 then Node(insert v l, x, r)
            elif comparer v x = -1 then Node(l, x, insert v r)
            else Node(l, x, r)

有效,但是,如果您要编写具有插入,查找,删除等功能的树操作模块,则要求客户端每次调用任何东西时都要传递排序函数.

It works, but if you're writing a module for tree operations with insert, lookup, removal, etc, you require clients to pass in an ordering function everytime they call anything.

如果F#支持函子,则其假想语法可能如下所示:

If F# supported functors, its hypothetical syntax might look like this:

type 'a Comparer =
    abstract Gt : 'a -> 'a -> bool
    abstract Lt : 'a -> 'a -> bool
    abstract Eq : 'a -> 'a -> bool

module Tree (comparer : 'a Comparer) =
    let rec insert v = function
        | Nil -> Node(Nil, v, Nil)
        | Node(l, x, r) ->
            if comparer.Lt v x then Node(insert v l, x, r)
            elif comparer.Gt v x then Node(l, x, insert v r)
            else Node(l, x, r)

仍然使用假设的语法,您将这样创建模块:

Still in the hypothetical syntax, you'd create your module as such:

module PersonTree = Tree (new Comparer<Person>
    {
        member this.Lt x y = x.LastName < y.LastName
        member this.Gt x y = x.LastName > y.LastName
        member this.Eq x y = x.LastName = y.LastName
    })

let people = PersonTree.insert 1 Nil

不幸的是,F#不支持函子,因此您必须依靠一些混乱的解决方法.对于上述情况,我几乎总是将"functor"与一些辅助帮助器函数一起存储在我的数据结构中,以确保正确地复制它:

Unfortunately, F# doesn't support functors, so you have to fall back on some messy workarounds. For the scenario above, I would almost always store the "functor" in my data structure with some auxillary helper functions to make sure it gets copied around correctly:

type 'a Tree =
    | Nil of 'a -> 'a -> int
    | Node of 'a -> 'a -> int * 'a tree * 'a * 'a tree

module Tree =
    let comparer = function
        | Nil(f) -> f
        | Node(f, _, _, _) -> f

    let empty f = Nil(f)

    let make (l, x, r) =
        let f = comparer l
        Node(f, l, x, r)

    let rec insert v = function
        | Nil(_) -> make(Nil, v, Nil)
        | Node(f, l, x, r) ->
            if f v x = -1 then make(insert v l, x, r)
            elif f v x = 1 then make(l, x, insert v r)
            else make(l, x, r)

let people = Tree.empty (function x y -> x.LastName.CompareTo(y.LastName))

这篇关于您能向我解释OCaml函子吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆