Control.Arrow与Data.Tuple.Extra

时间:2018-03-12 08:23:47

标签: haskell

我经常使用$(document).ready(function() { $('button').click(function() { $(".alert").delay(1000).addClass("in").fadeOut(4000, function(){ $(".alert").removeClass("in").show(); }); }) }); 库的以下功能:Data.Tuple.Extrafirstsecond***&&&。< / p>

both中有等效的(?)函数。事实上,我更喜欢Control.Arrow,因为我完全迷失了Data.Tuple.Extra的文档。

使用Control.Arrow是否有任何优势(例如从性能角度来看)?

2 个答案:

答案 0 :(得分:2)

我不熟悉Data.Tuple.Extra,但从查看文档来看,它似乎提供与Control.Arrow基本相同的功能。它的文档甚至声明:

  

Control.Arrow模块

中提供了其中一些功能

您可以使用dupe轻松实现bothControl.Arrow函数:

dupe = id &&& id
both f = first f >>> second f

示例:

Prelude Control.Arrow> dupe 42
(42,42)
Prelude Control.Arrow> both (+1) (41, 1336)
(42,1337)

使用Control.Arrow有什么好处吗?它更通用,因为它基于Arrow类型类,它再次源于类别理论......此外,该模块包含在base包中,因此它始终可用。

更一般的是,此处定义的both类型为Arrow a => a d c -> a (d, d) (c, c),这意味着您可以将其与任何Arrow一起使用,而不仅仅使用“基本”功能。例如,考虑一个Kleisli箭头。

print中的Prelude函数的类型为Show a => a -> IO (),由于IOMonad,因此您可以将其设为Kleisli实例,应用both,并在一对上运行它:

Prelude Control.Arrow> runKleisli (both $ Kleisli print) (42, 1337)
42
1337
((),())

我不知道这个特定的例子在现实生活中是否有用,但它表明both的这种实现更为通用。

BTW,对也是Bifunctor个实例,因此您也可以使用first中的secondData.Bifunctor。您可以使用both来定义Bifunctor

Prelude Data.Bifunctor> both f = bimap f f
Prelude Data.Bifunctor> :t both
both :: Bifunctor p => (a -> d) -> p a a -> p d d
Prelude Data.Bifunctor> both (+2) (40, 1335)
(42,1337)
Prelude Data.Bifunctor> both (*2) $ Right 21
Right 42
Prelude Data.Bifunctor> both (*2) $ Left 8
Left 16

请注意,由于这适用于任何Bifunctor,因此它适用于Either并添加到一对。

你不会从***获得&&&Data.Bifunctor,但是......

答案 1 :(得分:2)

在大多数Haskell用例中,使用Data.Tuple.Extra.firstControl.Arrow.first还是Data.Bifunctor.first并不重要 - 所有三个都将用作

first :: (b -> c) -> (b,d) -> (c,d)

...同样适用于second / *** / &&&ArrowBifunctor版本都以不同的方式更为通用,但通常可以根据标准元组/仿函数案例来概括

从实用角度讲,我建议使用Arrow版本,因为它们位于base。 (哦,我刚才注意到Bifunctor现在也在base,对此非常重要......)可以说,Arrow也是一个比Bifunctor更好的概括,因为它允许实际离开 Hask 类别。不幸的是,Control.Arrow本身并没有真正允许更多有趣的类别 - 它们很大程度上归结为Kleisli / Cokleisli类别(即不同服装中的monad),而对于那些通常更加实用的仅仅坚持{{1}记谱法等。

但是有许多数学类别不是do的实例,因为它们不允许在任何 Haskell类型之间进行映射,而只允许具有特定属性的类型。一个例子是 VectK ,即具有线性映射的向量空间的类别作为态射。在此类别中,Control.Category.Category是矩阵乘法,.是块矩阵对角堆叠,***是垂直连接。非常好的IMO,特别是因为它完全避免了你在Matlab,NumPy或hmatrix中得到的运行时维度检查的问题 - 所有这些都已经由编译器完成 - 它甚至支持无限维向量空间。

正如我所说,捕获它只适用于特定类型,标准&&& / Category类无法表达。实际上很容易在Haskell中表达它,因此我使用了constrained-categories package,用于在linearmap-category package中实现 VectK