在类别理论中,函子的定义应该包括两个功能:在对象上和在箭头上,这是非常明显的。但是,通常的Haskell Prelude.Functor
没有提到前者。这是为什么? pure
是对象上的那个函数吗?
具体来说,要使data F a
成为 Hask 中的终结符,应给出:
-- A function on objects:
omap :: a -> F a
-- A function on arrows:
fmap :: (a -> a') -> (F a -> F a')
对于“小” 类型的函数,例如Maybe
,将合适的数据构造函数(例如Just
)命名为对象上的函数似乎是安全的。对于种类更多的类型函数(可能是无限的,例如[⋅]
),我不太确定。选择\x -> [ ]
(一个小函子),\x -> [x]
,\x -> [x, x]
,...还是\x -> [x, x..]
会有所不同吗?还是这些都是“古典” 类别函子的实例化,尽管同样正确,但正确吗?
如果是这样,建议Prelude.Functor
实际上一次定义整个函子族是否正确?
建议offered in the answers to a question nearby,类型构造函数本身就是对象上的函数,我不准备接受。我们确实要求Functor
实例为fmap
的存在提供合法证据。同样,我们应该要求给出对象的术语级别函数omap
,不是吗?在 Hask 中,关于类型/术语的区别一定要引起混淆,无论是我个人还是在Haskell社区中传播的常识中。
具体来说,我可能建议我们实际上要讨论两个不同的类别:
然后,fmap
是 Hask 上的endofunctor的箭头函数,而类型构造函数是 Type 上的endofunctor的箭头函数。对类型集而不是值进行操作。
建议。正如@pigworker在评论中的善意解释,我对 Hask 的理解是错误的。但是,我不知道上述任何一项是否适用,如果考虑使用不同的类别术语,其中对象是一组值(可能是某些选定类型的所有可能值),而箭头是此类集合之间的(单态)函数。由于 hom 集也将是一个对象,因此fmap
和omap
(多态函数-实际上是一束箭头)都将按条件操作。同时,我的想法是 Term (只考虑与实际Haskell类型相对应的那些值集)的子类别可以与< strong>具有适当选择的函子的,该函子考虑了类方法,新类型等。按照这些思路进行施工是否存在一些明显的问题?
关于supposed duplicate question,由于上述原因,给出的答案不能满足我的好奇心。如果 Hask 不是适合我的查询的类别,则可以考虑使用其他一些类别。因此,我认为答案首先应该包含一个论点,即为什么要选择使用某个类别。