我知道Haskell中的许多名字都是受到范畴理论术语的启发,我正试图准确地理解类比的起点和终点。
我已经知道由于一些关于严格/懒惰和seq
的技术细节,hask
不(一定)是一个类别,但现在让我们先把那个放在一边。为了清楚起见,
hask
的对象是具体类型,即kind*
的类型。这包括像int->[Char]
这样的函数类型,但不包括像Maybe::*->*
这样需要类型参数的函数类型。但是,具体类型可能是Int::*
属于hask
。类型构造函数/多态函数更像是自然转换(或从hask
到自身的其他更一般的映射),而不是态射。hask
的态射是Haskell函数。对于两种具体类型
A
和
B
,HOM-集
HOM(A,B)
是签名为
A->B
的函数集合。
f给出。G
。如果我们担心严格性,我们可以重新定义合成,使之严格,或者在定义函数的等价类时小心。我不认为上面的技术细节与我下面的困惑有任何关系。我想我理解它的意思是说functor
的每个实例都是hask
类别中的endofunctor。也就是说,如果我们
class Functor (F :: * -> *) where
fmap :: (a -> b) -> F a -> F b
-- Maybe sends type T to (Maybe T)
data Maybe a = Nothing | Just a
instance Functor Maybe where
fmap f (Just x) = Just (f x)
fmap _ Nothing = Nothing
functor
实例可能
对应于从hask
到hask
的一个函数,其方式如下:
>
在hask
中给每个具体类型a
分配具体类型Maybea
对于hask
中的每个态射f::a->b
,我们分配给发送nothing nothing
和Just x Just(fx)
的态射Maybe a->mayb
。
范畴C上的常量(endo)函子是一个函子C:C
,它将范畴C的每个对象映射到固定对象C∈C
,并且C的每个态射映射到固定对象的恒等式态射ID_C:C
。
请考虑data.functor.const
。为了清楚起见,我将在这里重新定义它,区分类型构造函数const::*->*->*
和数据构造函数const::forall a,B。A->Konst a b
。
newtype Konst a b = Const { getConst :: a }
instance Functor (Konst m) where
fmap :: (a -> b) -> Konst m a -> Konst m b
fmap _ (Const v) = Const v
此类型进行检查是因为数据构造函数const
是多态的:
v :: a
(Const v) :: forall b. Konst a b
我可以相信konst m
是hask
类别中的内函子,因为在fmap
的实现中,
const v
显示为const m a
,由于多态性const v
显示为const m b
,由于多态性但是,如果我们试图把konst m::*->*
看作范畴理论意义上的常数函子,我的理解就会崩溃。
>
固定对象是什么?类型构造函数konst m
采用一些具体类型a
并给出一个konst ma
,至少从表面上看,对于每个a
都是不同的具体类型。我们确实希望将每个类型A
映射到固定类型M
。
根据类型签名,fmap
取一个f::a->b
并给出一个Konst m a->Konst m b
。如果konst m
类似于常数函子,则fmap
将需要将每个态射发送到固定类型m
上的同一性态射id::m->m
。
所以,下面是我的问题:
>
Haskell的const
函子在什么方面与范畴理论中的常数函子类似?
如果这两个概念不等价,那么用Haskell代码来表达范畴理论的常量函子(称它为simpleconst
)有可能吗?我快速尝试了一下,遇到了与多态wrt幻象类型相同的问题,如下所示:
data SimpleKonst a = SimpleConst Int
instance Functor SimpleConst where
fmap :: (a -> b) -> SimpleConst a -> SimpleConst b
fmap _ (SimpleConst x) = (SimpleConst x)
如果#2的答案是肯定的,如果是,那么在范畴理论意义上,这两个哈斯克尔函数是以什么方式相关联的呢?也就是说,在Haskell中,simpleconst
是const
,就像常量函子在范畴理论中是__?__
一样?
幻象类型是否会对将hask
想成一个类别造成问题?我们是否需要修改hask
的定义,以使对象实际上是类型的等价类,否则,如果没有幻影类型参数的存在,这些类型将是相同的?
它看起来像多态函数getconst::forall a,b。Konst a b->a
是从函子Konst m
到常数函子的自然同构
其自然转变规律为
_x=(Konst m f)。?y
。我很难证明这一点,因为我不知道如何正式地解释将(Const v)
从类型konst m a
转换为konst m b
的原因,而不是说“存在双射!”。
以下是上面尚未链接的可能相关问题/参考文献的列表:
- StackOverflow,“Haskell中的所有类型的类都有一个范畴理论的类比吗?”
- StackOverflow,“Haskell中的函子与范畴理论中的函子有何关系?”
- 维基图书,Haskell/类别理论
我们在这里遇到的问题是,从数学上讲,一个函子是一对相依的对,但它的一边(type->type
映射)位于Haskell的类型级世界,而另一边((a->b)->fa->fb
映射)位于值级世界。哈斯克尔没有一种方法来表达这样的对。functor
类通过只允许类型构造函数作为type->type
映射来绕过这个限制。
这样做的原因是类型构造函数是唯一的,即可以通过Haskell的typeclass机制为每一个构造函数分配一个定义良好的态射映射。但另一方面是,结果总是唯一的,因此最终出现的情况是,konst Int char
和konst Int bool
从技术上讲是不同的,尽管是同构的类型。
用一种更数学的方法来表达函子,需要一种单独的方法来在类型级别上识别你所说的函子。那么您只需要一个类型级映射(可以用类型族完成)和一个类型值级映射(typeclass):
type family FunctorTyM f a :: Type
class FunctorMphM f where
fmap' :: (a -> b) -> FunctorTyM f a -> FunctorTyM f b
data KonstFtor a
type instance FunctorTyM (KonstFtor a) b = a
instance FunctorMphM (KonstFtor a) where
fmap' _ = id
这仍然允许您拥有标准函子的实例:
data IdentityFtor
type instance FunctorTyM IdentityFtor a = a
instance FunctorMphM IdentityFtor where
fmap' f = f
data ListFtor
type instance FunctorTyM ListFtor a = [a]
instance FunctorMphM ListFtor where
fmap' f = map f
但实际使用起来会更别扭。您将注意到functormphm
类需要-XAllowAmbiguousTypes
来html" target="_blank">编译-这是因为不能从functortym f
推断出f
。(我们可以用内射类型族对此进行改进,但这只会使我们回到我们开始讨论的同一个问题:问题恰恰是常量函子不是内射的!)
对于modern Haskell,这是可以的,它只是意味着您需要明确地说明您使用的函数。(按理说,这往往是一件好事!)完整示例:
{-# LANGUAGE TypeFamilies, AllowAmbiguousTypes, TypeApplications #-}
type family FunctorTyM f a
class FunctorMphM f where ...
data KonstFtor a
...
data IdentityFtor
...
data ListFtor
...
main :: IO ()
main = do
print (fmap' @(KonstFtor Int) (+2) 5)
print (fmap' @IdentityFtor (+2) 5)
print (fmap' @ListFtor (+2) [7,8,9])
输出:
5
7
[9,10,11]
这种方法还有其他一些优点。例如,我们最终可以表示元组在每个参数中都是函子,而不仅仅是在最右边的参数中:
data TupleFstConst a
type instance FunctorTyM (TupleFstConst a) b = (a,b)
instance FunctorMphM (TupleFstConst a) where
fmap' f (x,y) = (x, f y)
data TupleSndConst b
type instance FunctorTyM (TupleSndConst b) a = (a,b)
instance FunctorMphM (TupleSndConst b) where
fmap' f (x,y) = (f x, y)
data TupleFtor
type instance FunctorTyM TupleFtor a = (a,a)
instance FunctorMphM TupleFtor where
fmap' f (x,y) = (f x, f y)
main :: IO ()
main = do
print (fmap' @(TupleFstConst Int) (+2) (5,50))
print (fmap' @(TupleSndConst Int) (+2) (5,50))
print (fmap' @TupleFtor (+2) (5,50))
(5,52) (7,50) (7,52)
在Haskell中有Hask,其中的对象是Haskell类型,而态性是Haskell函数。但是,type类有一个函数,它在这些类型(因此是对象而不是类别本身)之间进行映射: 和都是HASK中的对象。这是否意味着Haskell中的每个实例都是一个内函数,如果不是,真的表示一个函数吗?
从范畴理论的角度来看,这个答案包括以下陈述: ...事实是co和逆变函子之间没有真正的区别,因为每个函子都是协变函子。 更详细地说,从C类到D类的逆变函子F无非是F型的(协变)函子:COP→D,从C的相反类到D类。 另一方面,Haskell的和仅要求分别为实例定义和。这表明,从Haskell的角度来看,存在但不是的对象(反之亦然)。 因此,在范畴理论中,似乎“co和逆变函子之间没有真正的区别”,而
现在考虑一个成员类型为的typeclass。例如,可以想象一个类型类,它对应于组的类别(从技术上讲,是的子类别,其对象包含Haskell的所有类型)。概括: 问题2:Haskell中每个成员类型为的typeclass是否都对应于某个类别(从技术上讲:的某个子类别)? 由此可以提出下一个一般性问题: 一般问题:每一个Haskell类型类是否都对应于某种范畴理论的概念? Edit:至少,您可以说,由于
我有以下一段代码: 我可以想象编译器具有消除函数中的子句所需的所有信息。调用该函数的唯一代码路径来自main,它接受,因此它应该能够确定该代码路径未被使用。但是: 在GCC 12.2中,我们看到第二部分链接到。 如果我函数,这将消失: 我在这里错过了什么?有没有办法让编译器做一些更智能的工作?这发生在带有 C 和 。
本文向大家介绍C++常量详解二(常量形参,常量返回值,常量成员函数),包括了C++常量详解二(常量形参,常量返回值,常量成员函数)的使用技巧和注意事项,需要的朋友参考一下 1.常量形参 当形参有顶层const或者底层const的时候,传给它常量对象或者非常量对象都是可以的,在这里我们主要考虑形参无const, 而实参有const的情况,其实这里也十分简单,只需要记住一点:底层const的限制,就可
Haskell中的函子是一种可以映射不同类型的函数表示。它是实现多态性的高级概念。根据Haskell开发人员,列表、映射、树等所有类型都是Haskell函数的实例。 函子是一个内建的类,它的函数定义类似 − 根据这个定义,可以得出这样的结论:Functor是一个函数,它接受一个函数,比如,然后返回另一个函数。在上面的例子中,是函数的一种通用表示。 在下面的示例中,我们将看到Haskell Func