【问题标题】:Is there a name for this subset of bifunctors?这个双函子子集有名字吗?
【发布时间】:2022-01-26 18:41:11
【问题描述】:

双函子有一个带有这个签名的地图函数:

bimap :: (a -> b) -> (c -> d) -> p a c -> p b d 

你也可以有这样的地图:

othermap :: ((a, c) -> (b, d)) -> p a c -> p b d

具有此功能的类型是双函子的严格子集(您始终可以使用othermap 定义bimap,但反之则不行)。第二个签名有名字吗?

跟进:这个中间函数呢?

halfothermap :: ((a, c) -> b) -> (c -> d) -> p a c -> p b d

【问题讨论】:

  • 例如,如果您有ac,但不能同时拥有两者,您将如何为Either a c 实现此功能?
  • 我认为这个类没有多大用处。它太强大了——任何实现该签名的双函子类型都必须与包裹在元组周围的普通函子同构。
  • 我只看到提供的 Haskell 代码,并没有特定于 OCaml。 ocaml 标签真的相关吗? (如果这是一个带有 Haskell 示例的一般 FOP 问题,那么函数式编程标签可能更相关。
  • @Chris 好点,这实际上是一个 OCaml 问题,但我在 Haskell 中编写了它以改善回答者池。
  • 在这种情况下,您可能希望编辑问题以澄清。

标签: haskell types functional-programming functor bifunctor


【解决方案1】:

作为双函子的类型不需要与b 值具有相同数量的a 值。例如,考虑

data TwoLists a b = TwoLists [a] [b]

实现bimap 很容易,但othermap 是一个真正的问题,尤其是在其中一个列表为空的情况下。

othermap f (TwoLists [] (b:bs)) = TwoLists [] _

你可以在这里做什么?您需要调用f 将所有bs 转换为[d] 类型的列表,但只有当您手头有a 时才能调用该函数。

也许更糟糕的是一个根本没有 b 值的类型:

data TaggedFunction k a b = TaggedFunction a (k -> b)
instance Bifunctor (TaggedFunction k) where
  bimap f g (TaggedFunction a b) = TaggedFunction (f a) (g . b)

如何为这种类型实现othermap?您可以更新该函数,因为您手头有一个a,并且在您需要d 时将拥有一个b。但是您无法将a 替换为c,因为您无法使用b 来调用othermap 的函数。

所以你不能把这个函数放在 Bifunctor 中。也许你会问,为什么不把它放在一个新的类中呢?我认为 leftroundabout 是正确的,因为该类太受限制而无用。 othermap 只能在你的结构中有相同数量的as 和bs 时定义,即当你的结构是某个函子f 包裹在(a, b) 类型的元组上时。例如,我们可以定义而不是 TwoLists

newtype PairList a b = PairList [(a, b)]

并且可以有一个othermap 定义。但它只是

othermap f (PairList vs) = PairList (fmap f vs)

同样,我们可以定义而不是 TaggedFunction

newtype MultiFunction k a b = MultiFunction (k -> (a, b))

othermap 定义再次只是对fmap 的封装调用:

othermap f (MultiFunction g) = MultiFunction (fmap f g)

因此,想象定义此抽象的最佳方式可能不是类型类函数,而是一个普通函数,该函数对捕获此组合的类型进行操作:

newtype TupleFunctor f a b = TupleFunctor (f (a, b))

othermap :: Functor f => ((a, b) -> (c, d)) 
                      -> TupleFunctor f a b -> TupleFunctor f c d
othermap f (TupleFunctor x) = TupleFunctor (fmap f x)

【讨论】:

  • 谢谢!我确实是想把它作为双函子的一个子集来问,已经编辑了这个问题。
  • 这绝对是真的吗/as 和 bs 的数量必须相同的原因是什么,而不是至少一个? IE。为什么不能为(a, a, b) 定义othermap?我认为答案可能是“你必须做出任意选择,结果不会满足双函子定律”,但不确定/想不出一个例子。
  • 我还编辑了这个问题,跟进了一个似乎介于 bimapothermap 之间的函数。
【解决方案2】:

(扩展@glennsl 的评论...)

类型 p a c“包含”ac

但是(a, c) -> (b, d) 类型的函数需要a 类型的 c 被调用,而p a c 类型的值不需要'不一定要两者兼得。

othermap @Either :: ((a, c) -> (b, d)) -> Either a c -> Either b d
othermap f (Left x) = ?
othermap f (Right y) = ?

othermap 无法生成bd 类型的值,因为在这两种情况下它都无法调用f

第一个参数的类型暗示了一个与(,) 同构的双函子,但并非所有可能的双函子都是如此。实际上,othermapbimap 更具体。 (这里似乎有一个逆变关系,我不会尝试精确。)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-08-15
    • 1970-01-01
    • 1970-01-01
    • 2013-04-08
    • 1970-01-01
    • 2017-02-22
    • 2011-07-27
    • 1970-01-01
    相关资源
    最近更新 更多