【问题标题】:What is the general case of QuickCheck's promote function?QuickCheck的promote功能的一般情况是什么?
【发布时间】:2014-10-08 18:58:34
【问题描述】:

什么是具有类似于 QuickCheck 的promote 函数的结构的函子的总称,即以下形式的函数:

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

(这是flip $ fmap (flip ($)) :: f (a -> b) -> (a -> f b) 的倒数)。除了(->) r 和Id 之外,是否还有任何具有这种操作的函子? (我确信必须有)。谷歌搜索“快速检查提升”只出现了快速检查文档,在任何更一般的 AFAICS 上下文中都没有给出promote;在 SO 中搜索“快速检查提升”不会产生任何结果。

【问题讨论】:

  • sequenceA 相关吗?
  • 让我看看。代入sequenceA 的类型,我们将得到t = (->) a 和f = f。所以如果(->) a 有一个Traversable 实例,那么这个函数将存在于所有a。不过,我认为Traversable ((->) a) 需要(Bounded a, Enum a) 或等效项。
  • 不管怎样,universe 包家族提供了requisite Traversable instance。
  • @Daniel Wagner,啊,给定Finite,我猜这本质上是一回事。

标签: haskell functional-programming functor quickcheck category-theory


【解决方案1】:
(<*>) :: Applicative f => f (a -> b) -> f a -> f b
(=<<) :: Monad m => (a -> m b) -> m a -> m b

鉴于 Monad 是一个比 Applicative 更强大的接口,这告诉我们a -&gt; f b 可以比f (a -&gt; b) 做更多的事情。这告诉我们(a -&gt; f b) -&gt; f (a -&gt; b) 类型的函数不能是单射的。域大于共域,以手动方式。这意味着您不可能保留函数的行为。它只是不适用于泛型函子。

当然,您可以描述该操作是单射的函子。 Identity 和 (-&gt;) a 当然是例子。我敢打赌还有更多的例子,但没有什么能立即让我跳出来。

【讨论】:

    【解决方案2】:

    到目前为止,我发现了使用promote 态射构造f 的这些方法:

    • f = Identity
    • 如果 f 和 g 都具有 promote 则对函子 h t = (f t, g t) 也有
    • 如果 f 和 g 都具有 promote 则组合 h t = f (g t) 也有
    • 如果 f 具有 promote 属性并且 g 是任何反函子,则函子 h t = g t -&gt; f t 具有 promote 属性

    最后一个属性可以推广到 profunctors g,但是 f 将只是一个 profunctor,所以它可能不是很有用,除非你只需要 profunctors。

    现在,使用这四种结构,我们可以找到许多存在promote 的函子f 的例子:

    f t = (t,t)
    
    f t = (t, b -> t)
    
    f t = (t -> a) -> t
    
    f t = ((t,t) -> b) -> (t,t,t)
    
    f t = ((t, t, c -> t, (t -> b) -> t) -> a) -> t
    

    还要注意promote 属性意味着f 是指向的。

    point :: t -> f t
    point x = fmap (const x) (promote id)
    

    本质上是同一个问题:Is this property of a functor stronger than a monad?

    【讨论】:

    • 您能添加您建议的实际实例吗?例如,(t, t) 的这个实例是什么样的?在实现a -&gt; (b, b) -&gt; (a, a) -&gt; (b, b)的时候,是不是只对as都应用了输入函数,然后扔掉了2/4bs?
    • @AsadSaeeduddin (t, t) 的实例要求我们实现promote:: (a -&gt; (b, b)) -&gt; (a -&gt; b, a -&gt; b),而不是a -&gt; (b, b) -&gt; (a, a) -&gt; (b, b)。实施promote:: (a -&gt; (b, b)) -&gt; (a -&gt; b, a -&gt; b) 不会丢掉任何东西; promote f = (fst . f, snd . f)。尝试推导出一般结构:如果f 和g 有提升,那么h 在h a = (f a, g a) 的位置有提升。对于h,实现promote的方式只有一种,而且不会丢掉任何信息。
    【解决方案3】:

    Data.Distributive有

    class Functor g => Distributive g where
      distribute :: Functor f => f (g a) -> g (f a)
      -- other non-critical methods
    

    重命名你的变量,你得到

    promote :: (c -> g a) -> g (c -> a)
    

    为了清楚起见,使用稍微无效的语法,

    promote :: ((c ->) (g a)) -> g ((c ->) a)
    

    (c -&gt;) 是一个Functor,所以promote 的类型是distribute 类型的一个特例。因此每个Distributive 函子都支持你的promote。我不知道是否有人支持promote 但不支持Distributive。

    【讨论】:

    • Distributive 严格地强于promote。每个Distributive函子g都是可表示的:也就是说,存在一个常量类型b使得g t = b -&gt; t 。但是,诸如g t = (t -&gt; a) -&gt; t 之类的函子具有promote,但不可表示,因此不能为Distributive。更一般地,一个函子g 定义为g t = c t -&gt; h t 有promote 如果c 是任何反函子,而h 有promote. This construction can define a Distributable` 只有当c 是一个常数(反)函子。
    猜你喜欢
    • 1970-01-01
    • 2010-10-29
    • 1970-01-01
    • 2022-12-01
    • 2012-06-12
    • 1970-01-01
    • 1970-01-01
    • 2018-07-13
    • 1970-01-01
    相关资源
    最近更新 更多