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

问题描述 投票:14回答:4

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

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

为什么这样?

UPD换句话说:

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

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

math haskell monads functor category-theory
4个回答
10
投票

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

  • α -> F αFunctor F),
  • β -> M β(为Monad M)。

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

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

class Functor m => Monad m where
    return :: Id α -> m α
    join :: m (m α) -> m α

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

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

如果你采用类似于组合的运算符派生自标准绑定qazxsw poi:

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

你可以看到,它实际上是关于(>=>) :: Monad m => (α -> m β) -> (β -> m γ) -> (α -> m γ) f >=> g = \a => f a >>= g 。另见Kleisli category关于计算机科学中的monads。


7
投票

类别的对象与OO编程语言中的对象不同(我们更喜欢在Haskell中调用这些值;它们在类别理论中的含义是讨论过article on nLab)。相反,Hask的对象是类型。 Haskell heres是Hask中的endofunctors,即通过以下方式将类型关联到类型:

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

OTOH,Hask的箭头实际上是某些函数类型Functor的值。这些通过以下方式关联:

a -> b

3
投票

如果你有

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

然后类型构造函数instance Functor F where fmap = ... 是对象(它是类型)的动作,将类型F带到T类型,而F T是对函数fmapf :: T -> U的态射(函数)的动作。


3
投票

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

假设在Functor类型类中会有一个函数fmap f :: F T -> F U(或returnpureunit)。

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

很容易,嗯?

以下是普通的Functor实例:

((,) a)

那么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) for 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,我们应该采取BoolTrue?如果是False我们应该采取Either Int BoolLeft 0Right False

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

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

© www.soinside.com 2019 - 2024. All rights reserved.