【问题标题】:Where is the bifunctor for functions in haskell?haskell中函数的双函子在哪里?
【发布时间】:2018-07-18 08:09:52
【问题描述】:

我找不到 fmap 的双函子模拟。

解释:

对象的函子 - 数据类型构造函数。类型 - a -> f a

函数的函子 - fmap。类型 - (a -> b) -> (fa -> fb)

对象的双函子 - bimap f g 的结果,其中f :: (a -> a')g :: (b -> b')。类型 - p a b -> p a' b'

函数的双函子 - ?。类型 - p (a -> b) (c -> d) -> p (a' -> b') (c' -> d')

这就是为什么我认为双函子有这种类型(对吗?)并举个例子


更新


更新2

上图中的p (a -> b) (c -> d) -> p (a' -> b') (c' -> d')是双函子到双函子的态射,也是profunctor(因为所有的函数都是profunctor)

总结:

我认为p (a -> b) (c -> d) -> p (a' -> b') (c' -> d') 是函数的双函子,但事实并非如此。态射的双函子是bimap. Type: (a -> b) -> (α -> β) -> p a α -> p b β.

我认为p (a -> b) (c -> d) -> p (a' -> b') (c' -> d') 是不寻常的东西,但它不是,它只是功能

【问题讨论】:

  • 一个函数是一个profunctor,它在参数上是逆变的(contramap),在返回类型上是协变的(fmap)。它被称为dimapdimap :: (a -> b) -> (c -> d) -> p b c -> p a d。对于箭头类型:(a -> b) -> (c -> d) -> (b -> c) -> a -> d (hackage.haskell.org/package/profunctors-5.3/docs/…)
  • @YuvalItzchakov 按照我的例子,如何使用dimap 获得(Int, Float) -> (Id Int, Id2 Float) 类型的函数?
  • 如果我的理解正确的话,我认为标题可能会有点误导。我认为您是在说:任何函子都有两个“部分”,一个类型级部分(您称其为“对象的函子”,但我绝对建议说类型级)和值级部分(这是fmap) 并且您正在询问双函子的价值级别部分是什么。你问的是这个吗? (顺便说一句,如果是,“对象的函子”部分是不正确的。它处于类型级别,您正在谈论数据构造函数,如果我解释正确,它们是值级别)。
  • 再读一遍,我不太确信我之前阅读问题的方式是正确的。也许你可以稍微改写一下?您提到的所有内容具体是什么意思(例如 IdId2 以及类型签名 p (a -> b) (c -> d) -> p (a' -> b') (c' -> d') 与您要询问的其他内容有什么关系)?
  • @DavidYoung re what relation - 图片上有

标签: haskell category-theory


【解决方案1】:

对象的函子 - 数据类型构造函数。类型 - a -> f a

函数的函子 - fmap。类型 - (a -> b) -> (fa -> fb)

虽然这具有广泛的意义,但重要的是要意识到上面的箭头具有三种不同的含义。

对象的函子 - 数据类型构造函数。类型 - a ⟼ f a

函数的函子 - fmap。类型 - (a ⟿ b) ⟶ (f a ⟿ f b)

在哪里

  • 是一个类型级别的“映射到符号”,它将a 类型与f a 类型相关联。这与域为a 和codomain f a 的值级函数有任何关系。 (这些可以在 applicatives/monads 中找到,但那是另一回事。)
  • 是一些态射的类型构造函数。在 Hask 类别中,这些态射恰好是 Haskell 函数,但这只是一种特殊情况。
  • 是一个实际的函数类型构造函数。

您现在可能忘记了后两者之间的区别,但 在概念上确实完全不同。基本上, 就像你在 lambda

中写的箭头
Maybe :: Type -> Type
Maybe = \a ⟼ Maybe a

只是一种表达你对函数事物进行抽象的方式。

另一个可能不清楚的相关事情是您正在谈论的对象Haskell类型。不是值(就像 OO 对象一样)。

所以,我会这样写你上面给出的清单:

  • 函子

    • 对于对象:数据类型构造函数。种类Type -> Type,映射关联a ⟼ f a
    • 对于态射:fmap。类型:(a -> b) -> (f a -> f b)
  • 双函子

    • 对于对象:数据类型构造函数。种类Type×Type -> Type,或咖喱Type -> Type -> Type,映射关联a ⟼ b ⟼ p a b
    • 对于态射:bimap。类型:(a -> b) -> (α -> β) -> p a α -> p b β

实际上,Haskell 没有 或者你用a -> f a 写的东西。这将是一个类型级别的 lambda,但类型级别的函数实际上只能表示为 类型族,即最接近表达 a ⟼ f a 的是 type instance Functored a = f a

【讨论】:

  • @WillNess 它实际上是从问题中复制而来的。不确定这是故意的;在这一点上将f a 视为“原子”类型可能有点意义。但是,没有多大意义,我想我会改变这一点。
  • 我已经更新了图片,但是我还是不明白p (a -> b) (c -> d) -> p (a' -> b') (c' -> d')是怎样的profunctor,尤其是p(,)的时候。按照我的示例,如何使用 dimap 获取类型为 (Int, Float) -> (Id Int, Id2 Float) 的函数
  • @srghma functors 有 fmap ([x]-f-),bifunctors 有 bimap ([x,y]-(f,g)-),profunctors 有 dimap (-f-[x-y]-g-)。
  • @WillNess 对不起,前面的评论应该写成:我已经更新了图像,但我仍然不明白我的第二个图像的态射是如何具有@987654364 类型的@ 是 profunctor(正如@YuvalItzchakov 指出的那样),尤其是当p(,) 时。在有问题的图像上,我为图​​形的某些部分提供了示例。按照这个例子,这个态射应该有类型(Int, Float) -> (Id Int, Id2 Float),但我不明白如何使用dimap得到这个类型
  • @srghma 您使用 bimap 作为 chepner 的答案来执行此操作。函数本身可以被视为 profunctor,或用于实现 bifunctor(例如)行为,例如 bimap。 (IOW 你可以忽略那条评论,我认为这与这里无关。)
【解决方案2】:

(->) 不需要 Bifunctor 实例,只需 (,)

b1 :: a -> Id a
b2 :: a -> Id2 a

-- instance Bifunctor (,) where
--   bimap f g (x, y) = (f x, g y)

f :: (Int, Float) -> (Id Int, Id2 Float)
f = bimap b1 b2

【讨论】:

    猜你喜欢
    • 2010-09-27
    • 2017-09-30
    • 1970-01-01
    • 1970-01-01
    • 2014-06-18
    • 1970-01-01
    • 1970-01-01
    • 2010-09-16
    相关资源
    最近更新 更多