haskell 为什么Functor类没有返回函数?

ttvkxqim  于 2022-11-14  发布在  其他
关注(0)|答案(5)|浏览(195)

从范畴的Angular 来看,函子是遵循一些 axios 的两个Map对(一个在对象之间,另一个在范畴的箭头之间)。
我已经假设,每个Functor示例都类似于数学定义,即可以Map对象和函数,但Haskell的Functor类只有Map函数的函数fmap
为什么会这样呢?

UPD换句话说:

每一个单子类型M都有一个函数return :: a -> M a
函子类型F没有函数return :: a -> F a,只有F x构造函数。

ugmeyewa

ugmeyewa1#

首先,有两个层次:类型和值。由于Hask的对象是类型,因此只能使用类型构造函数来Map它们,类型构造函数的类型为* -> *

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

然后对于函子,你需要态射(即函数,是值)上的Map:它只是fmap :: (α -> β) -> (F α -> F β)
到目前为止,我想,我并没有说什么新的东西。但是重要的是,Monadreturn :: α -> M α并不像你所想的那样是αM α的Map器。关于单子的数学定义,return对应于从Id函子到M函子的自然变换,只是这个Id函子是隐式的。单子的标准定义还需要另一个自然变换M ◦ M -> M,所以把它翻译成Haskell就像

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

(As旁注:这两个自然变换实际上是单位变换和乘法变换,它们使单子成为内函子范畴中的幺半群。
实际的定义不同,但是等效的。请参阅Haskell/wiki
如果您使用从标准bind >>= :: m α -> (α -> m β) -> m β派生的类似于复合的运算符:

(>=>) :: Monad m => (α -> m β) -> (β -> m γ) -> (α -> m γ)
f >=> g = \a => f a >>= g

你可以看到,这实际上都是关于Kleisli category的,也可以参考article on nLab关于计算机科学中的单子。

p5fdfcr1

p5fdfcr12#

一个类别的对象和面向对象编程语言中的对象不一样(我们更喜欢在Haskell中调用那些值;它们在范畴论中的意义已经讨论过here)。相反,Hask的对象是 types。Haskell Functor s是Hask中的内函子,即通过以下方式将类型与类型相关联:
前奏曲〉:k也许
可能是::* -〉*
前奏曲〉:k 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)
dfuffjeb

dfuffjeb3#

虽然你在问题中使用了那些花哨的分类术语,并且应该对现有的答案完全满意,但这里还是试图给出一个相当琐碎的解释:
假设在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
所以你看,如果你在Functor上有一个return,一般来说你不能定义很多有效的functor示例(你需要施加一个像FunctorEmpty类型类的约束)。
如果你看一下FunctorMonad的文档,你会发现确实有Functor ((,) a)的示例,但没有Monad ((,) a)的示例,这是因为你不能为那个东西定义return

ivqmmu1c

ivqmmu1c4#

如果您有

instance Functor F where
    fmap = ...

那么类型构造函数F是对对象(是类型)采取类型T到类型F T的动作,而fmap是对态射(是函数)采取函数f :: T -> Ufmap f :: F T -> F U的动作。

z9smfwbn

z9smfwbn5#

在范畴论中,函子将所有对象从一个范畴Map到另一个范畴,但函子并不Map对象中的元素。

相关问题