为什么Functor类没有返回功能?

时间:2014-02-08 15:12:20

标签: math haskell monads functor category-theory

从分类的角度来看,仿函数是一对两个映射(一个在对象之间,另一个在类别的箭头之间),遵循一些公理。

我假设,每个Functor实例与数学定义类似,即可以映射对象和函数,但Haskell的Functor类只有映射函数的函数fmap

为什么会这样?

UPD 换句话说:

每个Monad类型M都有一个函数return :: a -> M a

Functor类型F没有函数return :: a -> F a,只有F x构造函数。

4 个答案:

答案 0 :(得分:10)

首先,有两个级别:类型和值。由于Hask的对象是类型,因此只能使用类型构造函数映射它们,类型构造函数具有* -> *类型:

  • α -> F α(适用于Functor F),
  • β -> M β(适用于Monad M)。

然后对于一个仿函数,你需要一个关于态射的映射(即函数,它们是值):它只是fmap :: (α -> β) -> (F α -> F β)

到目前为止,我想,我不是在说什么新东西。但重要的是,return :: α -> M α Monad α不是M α类型的映射器,您可能会想到return。关于monad的数学定义, Id对应于从M仿函数到Id仿函数的自然变换。只是这个M ◦ M -> M仿函数是隐含的。 monad的标准定义还需要另一种自然变换class Functor m => Monad m where return :: Id α -> m α join :: m (m α) -> m α 。所以将它翻译成Haskell就像

>>= :: m α -> (α -> m β) -> m β

(作为旁注:这两个自然变换实际上是单位和乘法,这使monad成为endofunctors类别中的 monoid

实际定义不同但是相同。请参阅Haskell/wiki

如果你采用类似于组合的运算符派生形式的标准绑定(>=>) :: Monad m => (α -> m β) -> (β -> m γ) -> (α -> m γ) f >=> g = \a => f a >>= g

{{1}}

你可以看到,它实际上都与Kleisli category有关。另请参阅关于计算机科学中monad的article on nLab

答案 1 :(得分:7)

一个类别的对象与OO编程语言中的对象相同(我们更喜欢在Haskell中调用那些;他们在类别理论中的意义进行了讨论here)。相反, Hask 的对象是类型。 Haskell Functor Hask 中的endofunctor,即通过以下方式将类型与类型相关联:

  

前奏> :k也许是   也许:: * - > *
  前奏> :k Int
  Int :: *
  前奏> :k也许Int   也许Int :: *

OTOH, Hask 箭头实际上是某些函数类型a -> b的值。这些以下列方式关联:

fmap :: ( Functor (f ::   t     ->     f t       {- type-level  -} ) )
             =>         (a->b)  ->  fmap(a->b)   {- value-level -}
                     ≡  (a->b)  ->  (f a->f b)

答案 2 :(得分:3)

如果你有

instance Functor F where
    fmap = ...

然后类型构造函数F是对类型T采用类型F T的对象(类型)上的操作,而fmap是对态射的操作(函数)将函数f :: T -> U转换为fmap f :: F T -> F U

答案 3 :(得分:3)

虽然您在问题中使用了那些奇特的分类术语,并且应该对现有答案完全满意,但这是尝试一个相当简单的解释:

假设成为Functor类型类中的函数return(或pureunit...)。

现在尝试定义Functor的一些常见实例:[](列表),Maybe((,) a)(带左侧组件的元组)

够了,嗯?

以下是普通的Functor实例:

instance Functor [] where
   fmap f (x : xs) = f x : fmap xs
   fmap _ []       = []

instance Functor Maybe where
   fmap f (Just x) = Just (f x)
   fmap _ Nothing  = Nothing

instance Functor ((,) a) where
   fmap f (x, y) = (x, f y)

现在Functor的return呢?

解释

instance Functor [] where
   return x = [x]

好的。那可能呢?

instance Functor Maybe where
   return x = Just x

好。现在元组:

instance Functor ((,) a) where
   return x = (??? , x)

你知道,不知道哪个值应该填充到该元组的左侧组件中。实例声明表明它的类型为a,但我们不知道该类型的值。也许类型a是Unit类型,只有一个值。但如果是Bool,我们应该True还是False?如果是Either Int Bool我们应该Left 0还是Right False还是Left 1

所以你看,如果你在Functors上有return,你就无法定义很多有效的函子实例(你需要强加一个类似于FunctorEmpty类型类的约束)。

如果您查看FunctorMonad的文档,您会看到确实存在Functor ((,) a)的实例,但Monad ((,) a)没有实例。这是因为你无法为那件事定义return