在过去的一年左右的时间里,我一直在哈斯克尔身边玩耍,我实际上已经开始'得到'它,直到Monads,Lenses,Type Families,......很多.
我即将离开这个舒适区,我正在转向OCaml项目作为日常工作.稍微研究一下语法,我正在寻找类似的更高级别的概念,例如functor.
我阅读了OCaml中的代码和仿函数的结构,但我似乎无法知道它们现在是否是Haskell和OCaml中的类似概念.简而言之,Haskell中的仿函数对我来说主要是一种在Haskell中提升函数的方法,我就是这样使用它(并且喜欢它).在OCaml中,它给我一种感觉,它更接近于编程到界面(例如,当使用比较函数创建一个集合或列表时),我真的不知道如何提升函数而不是仿函数.
有人可以解释我这两个概念是否相似,如果是这样,我错过了什么或没有看到什么?我用Google搜索了一下,似乎找不到明确的答案.
卡斯帕
Tik*_*vis 45
从实际的角度来看,你可以将OCaml和Haskell中的"函子"视为无关.正如你所说,在Haskell中,仿函数是允许你在其上映射函数的任何类型.在OCaml中,仿函数是由另一个模块参数化的模块.
在函数式编程中,什么是函子?很好地描述了两种语言中的仿函数以及它们的区别.
然而,顾名思义,两个看似不同的概念实际上存在联系!两种语言的仿函数都只是来自类别理论的概念的实现.
范畴理论是对范畴的研究,它们只是在它们之间具有"态射"的对象的任意集合.类别的概念是非常抽象的,因此"对象"和"态射"实际上可以是具有一些限制的任何东西 - 必须存在每个对象的身份态射,并且态射必须构成.
类别中最明显的例子是集合和函数的类别:集合是对象,而函数之间的集合是态射.显然,每一组都有一个身份功能,并且可以组成功能.通过查看像Haskell或OCaml这样的函数式编程语言可以形成一个非常相似的类:具体类型(例如类型的类型*)是对象,Haskell/OCaml函数是它们之间的态射.
在类别理论中,仿函数是类别之间的转换.它就像是类别之间的功能.当我们查看Haskell类型的类别时,仿函数本质上是一个类型级函数:它将类型映射到其他类型.我们关心的特殊类型的仿函数将类型映射到其他类型.这方面的一个很好的例子是Maybe:Maybe地图Int来Maybe Int,String对Maybe String等.它为每种可能的Haskell类型提供映射.
函子有一个额外的要求 - 他们必须映射类别的态射以及对象.特别是,如果我们有一个射A ? B和我们的仿函数映射A到A'和B到B',它必须映射射A ? B一些同态A' ? B'.举一个具体的例子,假设我们有类型Int和String.有一大堆Haskell函数Int ? String.为了Maybe成为一个合适的函子,它必须具备Maybe Int ? Maybe String每个函数的功能.
令人高兴的是,这正是fmap函数所做的 - 它映射函数.因为Maybe它有类型(a ? b) ? Maybe a ? Maybe b; 我们可以添加一些括号来获得:(a ? b) ? (Maybe a ? Maybe b).这种类型的签名告诉我们的是,对于我们拥有的任何正常函数,我们在Maybes上也有相应的函数.
因此,仿函数是类型之间的映射,它也保留了它们之间的函数.该fmap函数基本上只是对仿函数的第二个限制的证明.这使得很容易看出Haskell Functor类是如何只是数学概念的特定版本.
那么OCaml呢?在OCaml中,仿函数不是类型 - 它是一个模块.特别是,它是一个参数化模块:一个以另一个模块作为参数的模块.我们已经可以看到一些相似之处:在Haskell中,a Functor类似于类型级函数; 在OCaml中,仿函数就像一个模块级函数.真的,这是相同的数学思想; 然而,不是在Haskell中使用类型 - 而是在模块上使用它.
关于CSaml仿函数如何与CS网站上的类别理论仿函数相关的更多细节:SML中的仿函数与类别理论之间的关系是什么?.这个问题谈论的是SML而不是OCaml 本身,但我的理解是OCaml的模块系统与SML的模块系统密切相关.
总结:Haskell和OCaml中的函子是两个根本不同的结构,它们恰好是对同一个非常抽象的数学概念的反应.我觉得它很漂亮:).