Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/haskell/10.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/google-maps/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Haskell 两个函子的组合就是一个函子_Haskell_Functor_Category Theory - Fatal编程技术网

Haskell 两个函子的组合就是一个函子

Haskell 两个函子的组合就是一个函子,haskell,functor,category-theory,Haskell,Functor,Category Theory,在中,Petr Pudlak为Hask到Hask之间的函子以外的函子定义了CFunctor类。使用类型族重新编写它,看起来 class CFunctor f where type Dom f :: * -> * -> * -- domain category type Cod f :: * -> * -> * -- codomain category cmap :: Dom f a b -> Cod

在中,Petr Pudlak为Hask到Hask之间的函子以外的函子定义了
CFunctor
类。使用类型族重新编写它,看起来

class CFunctor f where
  type Dom f :: * -> * -> *               -- domain category
  type Cod f :: * -> * -> *               -- codomain category
  cmap :: Dom f a b -> Cod f (f a) (f b)  -- map morphisms across categories
使用看起来像的实例,例如

instance CFunctor Maybe where
  type Dom Maybe = (->)                   -- domain is Hask
  type Cod Maybe = (->)                   -- codomain is also Hask 
  cmap f = \m -> case m of
                   Nothing -> Nothing
                   Just x  -> Just (f x)
在范畴论中,只要F:C-->D是函子,G:D-->E是函子,那么组合GF:C-->E也是函子

我想用哈斯克尔来表达这一点。由于我不能编写
实例CFunctor(f.g)
我引入了一个包装器类:

newtype Wrap g f a = Wrap { unWrap :: g (f a) }
在编写
CFunctor
实例时,我得到了

instance (CFunctor f, CFunctor g, Cod f ~ Dom g) => CFunctor (Wrap g f) where
  type Dom (Wrap g f) = Dom f
  type Cod (Wrap g f) = Cod g
  cmap = undefined
但是我不知道
cmap
的实现应该是什么。有什么建议吗

PS所有这一切的最终原因是还引入了一个带有方法
unit
condit
的类
附加
,然后从附加自动派生monad实例。但首先,我需要向编译器展示两个函子的组合也是一个函子


我知道我可以在类型为
g(fa)
的对象上使用
cmap.cmap
,但这似乎有点像作弊——当然一个函子只是一个函子,编译器不必知道它实际上是另外两个函子的组合?

给定函子
f:C→ D
G:D→ E
,一个函子组合
G∘ F:C→ E
是类别
C
E
之间对象的映射,例如
(G∘ F) (X)=G(F(X))
和态射之间的映射,使得
(G∘ F) (F)=G(F(F))

这表明您的
CFunctor
实例应定义如下:

instance (CFunctor f, CFunctor g, Cod f ~ Dom g) => CFunctor (Wrap g f) where
  type Dom (Wrap g f) = Dom f
  type Cod (Wrap g f) = Cod g
  cmap f = cmap (cmap f)
但是,两次编写
cmap
将为您提供
domfab->codg(g(fa))(g(fb))
并且
cmap
在这种情况下具有类型
domfab->codg(wrappgfa)(wrappgfb)

我们可以从
g(f a)
Wrap g f
,反之亦然,但是由于实例声明没有对
Cod g
的结构做出任何假设,我们就不走运了

因为我们知道函子是类别之间的映射,所以我们可以利用
Cod g
类别
(在Haskell方面,这需要
Category(Cod g)
约束),这给了我们一些操作:

cmap f = lift? unWrap >>> cmap (cmap f) >>> lift? Wrap
然而,这需要一个方便的提升操作员
lift?
,将功能从
Hask
类别提升到
Cod g
类别。将
Cod g
写入
(~>)
,则
升降机的类型必须为:

lift? :: (a -> b) -> (a ~> b)

lift? unWrap  :: Wrap g f a ~> g (f a)
cmap (cmap f) :: g (f a)    ~> g (f b)
lift? Wrap    :: g (f b)    ~> Wrap g f b

lift? unWrap >>> cmap (cmap f) >>> lift? Wrap :: Wrap g f a ~> Wrap g f b
现在,该提升操作员至少有两种选择:

  • 您可以将构造从
    类别(Cod g)
    扩展到
    箭头(Cod g)
    ,在这种情况下,起重操作员变成
    arr
  • 或者,正如Sjoerd Visscher在评论中提到的那样,您可以使用以下事实:
    Wrap
    unWrap
    在运行时在语义上是
    id
    ,在这种情况下,使用
    unsafeceorce
    是合理的

对于Hask上的内函子,
DeriveFunctor
扩展肯定会自动处理(以及许多其他情况)。但是如果你必须手动实现它,我不明白为什么你会期望通过在每个函子上合成映射而在合成函子上映射更简单?基本上,
cmap f=cmap(cmap f)
是函子合成的定义,那么,为什么要用它来作弊呢?@C.A.McCann我很乐意写
cmap=cmap。cmap
作为实现,但对于类型构造函数
Wrap g f
(特别是,它需要
domfa b
Cod g(g(f a))(g(f b))
而不是
Cod g(Wrap g f a)(Wrap g f b)
。如上所述,我对Hask上的内函子以外的情况特别感兴趣。@DanielFischer因为
g(f a)
不仅仅是两个函子的组合,它本身也是一个函子,所以我想我应该能够在它上面使用
cmap
(类似于使用monad transformers时不必到处写
lift.lift.lift
,如果你能告诉编译器如何自动提升某些函数——这里我想告诉编译器如何使用
cmap
的单个应用程序跨两个类别映射态射)。我的意思是在
cmap
的定义中使用它来定义
Wrap f g
。但是,看看它,我不知道如何对一般
g
这样做;只有
Cod g=(>)
是显而易见的。我怀疑在存在类型族的情况下,
unsafecterce
可能是一个不好的选择。无可否认,我还没有弄清楚任何细节。