Haskell和OCaml中的函子如何相似?
在过去的一年里,我一直在Haskell玩耍,我实际上已经开始“得到”它,直到Monads,Lenses,Type Families,......很多。
我即将离开这个舒适区,我正在转向一个OCaml项目作为日常工作。 仔细查看语法,我正在寻找类似的更高层次的概念,例如functor。
我阅读了OCaml中的代码和一个函数的结构,但我似乎无法弄清楚他们现在是否在Haskell和OCaml中有类似的概念。 简而言之,Haskell中的函数对我来说主要是一种在Haskell中提升函数的方法,我使用它(并且像这样)。 在OCaml中,它给了我一种更接近编程到接口的感觉(例如,当创建一个集合或一个列表时,使用该比较函数),而我真的不知道如何举例来说,通过函子提升函数等等。
有人可以解释我是否这两个概念是相似的,如果是的话,我错过了什么或没有看到? 我搜索了一下,似乎并没有明确的答案。
卡斯帕
从实际的角度来看,您可以将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
for each each。
令人高兴的是,这正是fmap
函数所做的 - 它映射函数。 对于Maybe
,它有类型(a → b) → Maybe a → Maybe b
; 我们可以添加一些括号来得到: (a → b) → (Maybe a → Maybe b)
。 这种类型签名告诉我们的是,对于我们所有的普通函数,我们也有一个相应的函数Maybe
。
所以一个仿函数是类型之间的映射,也保留它们之间的函数。 fmap
函数基本上是对函数的第二个限制的证明。 这可以很容易地看出Haskell Functor
类只是数学概念的特定版本。
那么OCaml呢? 在OCaml中,函子不是一种类型 - 它是一个模块。 特别是,它是一个参数化模块:一个将另一个模块作为参数的模块。 我们已经可以看到一些相似之处:在Haskell中, Functor
就像是一个类型级别的函数; 在OCaml中,仿函数就像一个模块级函数。 所以真的,这是同一个数学概念; 然而,不是在类型上使用类似于Haskell,而是在模块上使用它。
关于OCaml函子如何与CS网站上的类别理论函子相关的详细信息有很多:SML中的函子和类别理论之间的关系是什么? 这个问题本身谈论SML而不是OCaml,但我的理解是OCaml的模块系统与SML的模块系统非常相关。
总之:Haskell和OCaml中的函数是两个根本不同的结构,它们恰好是同一个非常抽象的数学概念的变体。 我认为它非常整洁:)。
链接地址: http://www.djcxy.com/p/47731.html