可能重复:
在函数式编程中,什么是函子?
我对OCaml不太了解,我研究F#有一段时间了,很了解。
他们说 F# 缺少 OCaml 中存在的函子模型。我试图弄清楚函子到底是什么,但维基百科和教程对我帮助不大。
你能帮我解开这个谜吗?提前致谢 :)
编辑:
我已经抓住了重点,感谢所有帮助过我的人。您可以将问题作为完全重复的内容结束:在函数式编程中,什么是函子?
可能重复:
在函数式编程中,什么是函子?
我对OCaml不太了解,我研究F#有一段时间了,很了解。
他们说 F# 缺少 OCaml 中存在的函子模型。我试图弄清楚函子到底是什么,但维基百科和教程对我帮助不大。
你能帮我解开这个谜吗?提前致谢 :)
编辑:
我已经抓住了重点,感谢所有帮助过我的人。您可以将问题作为完全重复的内容结束:在函数式编程中,什么是函子?
如果您来自 OOP 世界,那么将模块视为类似于静态类可能会有所帮助。与 .NET 静态类类似,OCaml 模块具有构造函数;与 .NET 不同,OCaml 模块可以在其构造函数中接受参数。函子是您传递给模块构造函数的对象的一个听起来很吓人的名称。
因此,使用二叉树的规范示例,我们通常会在 F# 中这样编写它:
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
使用<
and>
运算符比较两个类型的对象呢?
在幕后,它在做这样的事情:
> let gt x y = x > y;;
val gt : 'a -> 'a -> bool when 'a : comparison
好吧,如果你有一个类型的对象Person
没有实现那个特定的接口怎么办?如果您想动态定义排序功能怎么办?一种方法是按如下方式传入比较器:
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)
它可以工作,但是如果你正在编写一个用于插入、查找、删除等的树操作的模块,你需要客户端在每次调用任何东西时传递一个排序函数。
如果 F# 支持仿函数,它的假设语法可能如下所示:
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)
仍然在假设的语法中,您将这样创建您的模块:
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# 不支持仿函数,因此您必须求助于一些混乱的解决方法。对于上述情况,我几乎总是将“函子”与一些辅助辅助函数一起存储在我的数据结构中,以确保它被正确复制:
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 课程中查看此数据结构:
http://www.cs.cornell.edu/Courses/cs3110/2009fa/lecturenotes.asp
函子讲座: http ://www.cs.cornell.edu/Courses/cs3110/2009fa/lectures/lec10.html
以及使用仿函数的展开树实现: http ://www.cs.cornell.edu/Courses/cs3110/2009fa/recitations/rec-splay.html