是否存在投标分配?我需要什么功能?

时间:2017-12-22 17:15:43

标签: haskell math category-theory bifunctor distributive

我有代码(实际上是在C#中,但这个问题与C#无关,所以我会谈到我在Haskell中所说的所有类型),我在Either a b内工作。然后我bind一个带有签名的函数,在Haskell中说的是b -> (c, d),之后我想将c拉到外面并在左边的情况下默认它,即我想要{ {1}}。现在这种模式多次出现在我写的一个特定服务中,所以我提出了一种方法来实现它。然而,无论什么时候,我都会困扰我#34;这样的方法没有理解正确的理论基础。换句话说,我们在这里处理什么抽象?

我在一些F#代码中遇到了类似的情况,其中我和我的任何一对都被颠倒了:(c, Either a d)。我问朋友这是什么,他让我转向traverse,这使我非常高兴,尽管由于缺乏类型类,我必须在F#中进行可怕的单态实现。 (我希望我可以将Visual Studio中的 F1 重新映射到Hackage;它是我编写.NET代码的主要资源之一)。但问题是遍历是:

(a, b) -> (b -> Either c d) -> Either c (a, d)

这意味着当你从一对开始想要"绑定"要么是一个,要么不起作用,当你开始使用一个并希望最终得到一对,因为对不是Applicative

但是我想到了我的第一个案例,那个不是class (Functor t, Foldable t) => Traversable t where traverse :: Applicative f => (a -> f b) -> t a -> f (t b) 的案例,并且意识到"在左边案例中默认traverse"可以通过在左边的情况下进行映射来完成,这会将问题更改为具有此形状:c我认为这是我们在算术中使用乘法和加法看到的模式:Either (c, a) (c, d) -> (c, Either a d)。我还记得布尔代数和集合理论中存在相同的模式(如果内存服务,a(b + c) = ab + ac)。显然,这里有一些抽象的代数结构。但是,内存不起作用,我不记得它被称为什么。维基百科上的一点点问题迅速解决了这个问题:这些是distributive法律。快乐,快乐,凯美特给了我们distribute

A intersect (B union C) = (A intersect B) union (A intersect C)

它甚至有一个class Functor g => Distributive g where distribute :: Functor f => f (g a) -> g (f a) ,因为它与cotraverse是双重的!可爱!!但是,我注意到没有Travsersable实例。哦,哦。因为,是的,"默认(,)值"进入这一切?然后我意识到,哦,我可能需要基于bifunctor的投标分配?也许是bitraversable的双重?从概念上讲:

c

这似乎是我所谈论的分配法的结构。我在Haskell找不到这样的东西,因为我实际上在编写C#,所以对我来说并不重要。然而,对我来说重要的是不要提出虚假的抽象,并且尽可能地识别我的代码中的合法抽象,无论它们是否表达,为了我自己的理解< /强>

我目前在我的C#代码中有一个class Bifunctor g => Bidistributive g where bidistribute :: Bifunctor f => f (g a b) (g a c) -> g a (f b c) 函数(扩展方法)(什么是黑客,对吧!)。我是否完全偏离基础来创建一个(是的,可悲的单形).InsideOut(<default>)函数(扩展方法)来替换它并映射&#34;默认&#34;左边的情况下,在调用它之前进入左边的情况(或者只是识别&#34;&gt;分配&#34;字符&#34;内部&#34;)

2 个答案:

答案 0 :(得分:6)

bidistribute无法实现。考虑一些简单的例子

data Biconst c a b = Biconst c

instance Bifunctor (Biconst c) where
  bimap _ _ (Biconst c) = Biconst c

然后我们有专业化

bidistribute :: Biconst () (Void, ()) (Void, ()) -> (Void, Biconst () () ())
bidistribute (Biconst ()) = ( ????, Biconst () )

显然没有办法填补空白,需要输入Void类型。

实际上,我认为你真的需要Either(或者与它同构的东西),而不是任意的bifunctor。那你的功能只是

uncozipL :: Functor f => Either (f a) (f b) -> f (Either a b)
uncozipL (Left l) = Left <$> l
uncozipL (Right r) = Right <$> l

已定义in adjunctions(找到using Hoogle)。

答案 1 :(得分:2)

根据@ leftaroundabout的提示来查看附件,除了他在his answer中提到的uncozipL,如果我们推迟&#34;默认第一个值为左边的那对&#34;,我们也可以用unzipR来解决这个问题:

unzipR :: Functor u => u (a, b) -> (u a, u b)

然后,仍然需要映射对中的第一个元素,并使用类似either (const "default") id的值拉出值。有趣的是,如果你使用uncozipL,你需要知道其中一个是一对。如果您使用unzipR,则需要知道其中一个是其中之一。在这两种情况下,你都不使用抽象的bifunctor。

此外,我正在寻找的模式或抽象似乎是distributive lattice。维基百科说:

  

如果L中的所有x,y和z具有以下附加恒等式,则格子(L,∨,∧)是分布的:

x ∧ (y ∨ z) = (x ∧ y) ∨ (x ∧ z).

这正是我在很多不同地方观察到的属性。