在范畴论中,函子是两个范畴之间的同态。在 Haskell 中,据说应用函子允许我们在“函子内部”应用函数。有人可以将“函子内部的函数”这个词翻译回数学或提供其他一些见解吗?(我知道函子可以是Maybe
,[]
等等,但仍然很难理解这个概念。)
2 回答
我的范畴论一点都不强(我是从 Haskell 的编程方面开始的,最近一直在尝试学习它的一些概念的范畴论基础)。但这就是我所拥有的:
在 Haskell 中,仿函数是类型构造函数,这意味着它从一般类型映射到“仿函数中的类型”。
在范畴论中,函子从一个范畴的对象映射到另一个范畴的对象。
当将范畴理论应用于 Haskell 时,我们假设我们正在使用范畴Hask,即 Haskell 类型的范畴。
所以 Haskell 函子不是一般范畴论的函子。它们都从Hask映射到Hask的子类别(因为f a
某些函子f
和任意类型a
的类型仍然是 Haskell 类型)。例如,函子将HaskMaybe
中的对象(类型)映射到 form 的类型类别。Maybe a
函数在 Haskell 中是一等的,所以函数类型是完全普通的类型(并且是Hask的对象),所以函子也将函数类型映射到“函子中的函数类型”。因此,短语“函子内的函数”是一种类型中的值的简写,该类型是通过将函子应用于函数类型而产生的。egJust (+1)
是类型中的一个特定值Maybe (Int -> Int)
,它是Maybe
仿函数映射到的对象(类型) Int -> Int
。
因此,“应用函子”是一个具有一些额外规则的函子,这些规则足以获取作为函子“目标”类别对象的类型中的函数的值,并将这些值应用于目标类别中的其他类型值.
再次Maybe
举个例子,如果我们只知道它是一个函子,它给了我们对象Int -> Char
与Maybe (Int -> Char)
之间、对象Int
与Maybe Int
之间以及对象Char
与之间的对应关系Maybe Char
。但是,虽然我们有能力接受一个值 inInt -> Char
和一个值 inInt
并产生一个值 in Char
,Maybe
但作为一个函子并不能保证我们有能力对一个值 inMaybe (Int -> Char)
和一个值 in进行一些相应的操作Maybe Int
。
当我们也知道它是一个应用函子时,我们确实有能力接受一个值 inMaybe (Int -> Char)
和一个值 inMaybe Int
并产生一个值 in Maybe Char
,这满足了将Int -> Char
值应用于Int
值的某些属性。
据我所知,从纯范畴论的角度来看,应用函子并不是很有趣。也许这是因为范畴论关注对象之间的关系,这对应于 Haskell 中的类型,但从编程的角度来看,应用函子是由这些类型中的值之间的关系驱动的?(我们希望使用仿函数获得的“函数类型”中的值仍然能够应用于进行计算的事物)。
翻译回数学
在一个封闭的幺半群范畴中,有一个“指数”的概念,它“内化”了态射关系。然后,您可以评估这些指数。也就是说,您有一种说法(请原谅我的想法,Stackoverflow 缺少 mathjax)
eval : (a ~> b,a) -> b
以及用于currying和uncurrying的元操作。
“应用函子”以“适用”方式映射指数,F (a ~> b)
可以与 a 组合F a
以获得F b
. 这是因为应用函子是单曲面函子,所以它们有一个操作(在目标类别中)
f a -> f b -> f (a,b)
当您还 fmap eval 时,它会ap
从 Haskell 给您。
我怀疑这是否有用,
哈斯克尔
理解应用函子的最好方法是查看类型
class Functor f => Applicative f where
pure :: a -> f a
<*> :: f (a -> b) -> f a -> f b
一个简单的例子是
newtype Id a = Id a
instance Applicative Id where
pure a = Id a
Id f <*> Id a = Id (f $ a)
Id
也是一个Monad
。事实上,所有Monad
的 s 都是Applicative
。
pure = return
mf <*> mx = do f <- mf
x <- mx
return (f x)
一个更有趣的例子是无限序列
data Seq a = Seq a (Seq a)
instance Applicative Seq where
pure a = Seq a (pure a)
(Seq f fs) <*> (Seq x xs) = Seq (f x) (fs <$> xs)
您可以将其视为等同zipWith $
于列表。所有Monad
s 都是Applicative
,但我认为无限序列很有趣,因为相应的 monad 实例......不明显(而且相当慢)。它将作为练习留给读者(顺便说一句,我正在从我记得读过的东西中锻炼这个例子/练习,我认为 pigworker 写在这个网站上)。