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

uhb*_*f19 15 math monads haskell functor category-theory

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

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

为什么这样?

UPD换句话说:

每个Monad类型M都有一个功能return :: a -> M a.

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

lau*_*lic 11

首先,有两个层次:类型和价值.由于Hask的对象是类型,您只能使用类型构造函数映射它们,类型构造函数具有以下* -> *类型:

  • ? -> F ?(因为Functor F),
  • ? -> M ?(为Monad M).

那么对于一个仿函数,你需要一个关于态射的映射(即函数,它们是值):它只是fmap :: (? -> ?) -> (F ? -> F ?).

到目前为止,我想,我不是说任何新的东西.但重要的是return :: ? -> M ?Monad是不是一个类型的映射?M ?,你可能认为.关于monad的数学定义,return对应于Idfunctor到Mfunctor 的自然转换.只是这个Id仿函数是隐含的.monad的标准定义还需要另一种自然变换M ? M -> M.所以将它翻译成Haskell就好了

class Functor m => Monad m where
    return :: Id ? -> m ?
    join :: m (m ?) -> m ?
Run Code Online (Sandbox Code Playgroud)

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

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

如果你采用类似于组合的运算符派生形式的标准绑定>>= :: m ? -> (? -> m ?) -> m ?:

(>=>) :: Monad m => (? -> m ?) -> (? -> m ?) -> (? -> m ?)
f >=> g = \a => f a >>= g
Run Code Online (Sandbox Code Playgroud)

你可以看到,它实际上是关于Kleisli类别的.另请参阅有关计算机科学中monad的nLab文章.


lef*_*out 7

一个类的对象是一样的面向对象编程语言的对象(我们更愿意把这些在Haskell,他们的意思范畴论讨论这里).相反,Hask的对象是类型.Haskell Functor是Hask中的endofunctors,即通过以下方式将类型关联到类型:

Prelude>:k Maybe
Maybe ::* - >*
Prelude>:k Int
Int ::*
Prelude>:k也许Int
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)
Run Code Online (Sandbox Code Playgroud)

  • 这不太正确.如果您希望将仿函数视为_morphisms_,那么它只是一个:在类别类别中,对象是类别,类别_A_和类别_B_之间的态射是将_A_的对象映射到_B_的对象的仿函数以及_A_的态射对_B_的态射.在这个例子中,`Maybe`是**Hask**的endofunctor,即类别类别中的endomorphism,正如我所说,它将对象映射到对象(例如_type_`Int`以键入`Maybe Int`)和态射到态射(`length :: String - > Int`到`fmap length :: Maybe String - > Maybe Int`) (5认同)

scr*_*avy 7

尽管您在问题中使用了那些花哨的分类术语并且应该对现有答案完全满意,但这里尝试进行一个相当简单的解释:

假设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)
Run Code Online (Sandbox Code Playgroud)

returnFunctor 现在怎么样?

列表:

instance Functor [] where
   return x = [x]
Run Code Online (Sandbox Code Playgroud)

好吧。也许呢?

instance Functor Maybe where
   return x = Just x
Run Code Online (Sandbox Code Playgroud)

好的。现在元组:

instance Functor ((,) a) where
   return x = (??? , x)
Run Code Online (Sandbox Code Playgroud)

您会看到,不知道应该将哪个值填充到该元组的左侧组件中。实例声明说它有一个类型a,但我们不知道该类型的值。也许类型 a 是Unit只有一个值的类型。但如果是的话Bool,我们应该采取True还是False?如果是,Either Int Bool我们应该采取Left 0orRight False或 吗Left 1

所以你看,如果你有一个returnon Functors,你通常无法定义很多有效的 functor 实例(你需要施加像 FunctorEmpty 类型类这样的约束)。

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

  • 优秀的补充!谢谢。 (3认同)