在两个类别之间定义 haskell 中的函子的示例(与加法和乘法幺半群密切相关)

Example of defining a functor in haskell between two categories (which are closely related to additive and multiplicative monoids)

我试图调和函子的数学概念和它的 haskell 概念。 这篇文章http://brianshourd.com/posts/2012-10-26-tilt-functors-in-haskell.html解释了一点,但也许有人可以为以下情况提供一个例子:

假设我定义了以下类别

Add: 其中对象是0,1,2,3,....,态射是(0+), (1+), (2+), ... (0+)是id变形。

Mul: 其中对象是0,1,2,3,....,态射是(0*), (1*), (2*), ... (1*)是id变形。

组成是(.)

如何在 Haskell 中定义这两个类别之间的函子(如果可能并且我上面描述的完全是类别)

谢谢

编辑:根据@chi 的建议,我稍微澄清一下这个问题。我更感兴趣的是你如何将 put/translate 转换为 Haskell 这两个类别之间的任何函子(而不是存在一个函子,例如将任何数字映射到 42 并将任何态射映射到 (1*) 作为@chi sugested)

编辑 2:另一种提问方式是,如何协调这两个语句 "the Functor typeclass, which is basically for things that can be mapped over" 与 "Given categories C and D, a functor F:C→D is a rule that assigns to each object A in C an object F(A) in D. It also assigns to every morphism f:A→B of objects of C a morphism F(f):F(A)→F(B)"。如果类型构造函数 [] (lists) 是一个函子,它连接的两个类别是什么,它是如何映射这两个类别之间的对象和态射的

如果你查看 Haskell 中 class Category 的定义,你会看到这个。

class Category cat where
  id :: cat a a 
  (.) :: cat b c -> cat a b -> cat a c

看,如果类别中的对象是 Int,那么您需要定义那些函数,其中 abcInt秒。当集合中的对象是类型而不是值时,这很好。所以你不能让它们成为 Category.

的实例

也在看fmap

 fmap :: (a -> b) -> f a -> f b

你可以看到它只对类型有意义(因此属于 Hask 类别)。如果对象是整数,你会传递像 4 --> 5-> 这样的态射只适用于类型。

(0+)IntInt的态射。你需要一个从 2 到 5 的态射。

也许会是这样的:

data IntMorphism = IdMorphism | IntMorphism Int Int

comp :: IntMorphism -> IntMorphism -> IntMorphism
comp IdMorphism m = m
comp m IdMorphism = m
comp  (IntMorphism y' z) (IntMorphism x y)
  | y /= y' = error "can't compose"
  | otherwise = IntMorphism x z

f1 :: Int -> Int
f1 = (+5)

f2 :: IntMorphism -> IntMorphism
f2 IdMorphism = IdMorphism
f2 (IntMorphism x y) = IntMorphism (f1 x) (f1 y)

函子定律成立。特别是:

f2 (comp (IntMorphism y z) (IntMorphism x y))
= f2 (IntMorphism x z)
= IntMorphism (f1 x) (f1 z)
= comp (IntMorphism (f1 y) (f1 z)) (IntMorphism (f1 x) (f1 y))
= comp (f2 (IntMorphism y z)) (f2 (IntMorphism x y))

当然,因为它处理的是值,所以不能使用base中定义的类型类,都是在运行时完成的。

问题在于 Haskell 的 Functor 仅表示某种函子:来自 Haskell 类型和函数类别的函子 (Hask) 到本身。 Functor 将类型映射到类型(Hask 的对象)并将函数映射到函数(Hask 的态射)。例如,Maybe Functor 将任何给定类型 a 映射到类型 Maybe a 并使用 fmap 将给定函数 a -> b 映射到函数 Maybe a -> Maybe b.

Hask的范畴中,对象是类型,态射是函数。您的类别将整数作为其对象,因此不符合 Functor 的模式,因此以这种形式提出问题不太有意义,至少对于 Functor 输入 class.