为什么`pure`只适用于Applicative而不是Functor?
阅读这本关于Haskell和Category Theory基础知识的Wikibook,我了解了Functors:
函子本质上是类别之间的转换,因此给定类别C和D,函子F:C - > D
将C中的任何对象A映射到F(A),D中。
映射态射f:在C中的A→B到F(f):在D中的F(A)→F(B)
......听起来很好。 稍后提供一个例子:
我们也有一个示例实例:
instance Functor Maybe where
fmap f (Just x) = Just (f x)
fmap _ Nothing = Nothing
以下是关键部分:类型构造函数Maybe可以将任何类型的T传递给一个新类型Maybe T.另外,限制为fim的类型可以使用函数a - > b函数Maybe a - > Maybe b。 但就是这样! 我们定义了两个部分,一部分将Hask中的对象带到另一个类别中的对象(Maybe类型和Maybe函数上定义的类型和函数),另一部分将Hask中的态射作为这个类别中的态射。 所以也许是一个仿函数。
我理解fmap
的定义是如何关键的。 我对“类型构造函数Maybe”如何提供第一部分感到困惑。 我宁可期待像pure
东西。
如果我说得对, Maybe
宁可将C
映射到D
(因此在类别层次上是一种态度主义,这可能是一个Functor的要求)
我想你可以像这样重新修改我的问题:是否有Functor没有明显的pure
实现?
我认为你会在类型和值之间感到困惑。 这是一个仿函数的定义:
让C和D成为类别。 从C到D的函数 F是一个映射:
(f):F(X)→F(Y)∈D,使得以下条件成立:
一个类包含对象之间的对象和态射。
Haskell中的所有代码都是Hask的一部分,Haskell类。 在Hask中:
因此,Haskell中的所有Functor
实例都是从Hask到Hask的函数(即它们是endofunctors)。
更严格地说,对于Haskell中Functor
所有实例:
C = Hask
。 D = Hask
。 现在,每个函数F是一个映射,它与每个对象X∈C关联一个对象F(X)∈D。
f : * -> *
。 事实上,这正是Haskell中定义Functor
类型的方式:
class Functor (f : * -> *) where
fmap :: (x -> y) -> (f x -> f y)
在这里, fmap
是fmap
函数的第二部分。 这是一个从值到值的函数。 然而, Functor
本身是一个类型构造器(即从类型到类型的映射)。 这就是Maybe
是一个函子, []
是一个函子,但是Maybe Int
和[Int]
不是函子。
请注意, pure
并不构成函子定义的第一部分,因为它是从X实例到F(X)实例的映射(即它是从值到值的函数)。 但是,我们需要从X到F(X)的映射(即从类型到类型的映射)。
如果我说得对, Maybe
宁可将C
映射到D
(因此在类别层次上是一种态度主义,这可能是一个Functor的要求)
不是真的,因为C
和D
有类别,而不是Haskell类型。 Functor
(即类型类的一个实例,与通常的函子相对)是Hask类别(Haskell类型和函数的类别)到Hask本身的映射 ; 也就是说, C
和D
在这种情况下都是Hask 。 Wikibook章节提到在Hask的Functors部分。 在您的示例中, Maybe
类型构造函数通过将类型a
( Hask中的一个对象)添加到Maybe a
类型( Hask中的另一个对象)来提供映射的第一部分。
我想你可以像这样重新修改我的问题:是否有Functor
没有明显的pure
实现?
一个例子是Functor
, (,) a
。 fmap
很容易写- f (x, y) -> (x, fy)
-但pure
和(<*>)
需要Monoid
约束上a
,因为就没有处理多余的方式a
否则值。 有关更多讨论和其他示例,请参阅非函数/函数/应用/ Monad的良好示例?
我会说Applicative
实例对于Either
是一种延伸(我只需Bifunctor
一个Bifunctor
的实例就Bifunctor
,但是另一方面将它用作Monad是很方便的),并且会(IMHO)成为不适合的东西,如:
data ABC a = A a | B a | C a
A,B,C全部“同样好”。 由于没有明显的选择应该使用pure
,所以根本不应该提供它。 虽然fmap
仍然非常好。
上一篇: Why is `pure` only required for Applicative and not already for Functor?