gpt4 book ai didi

haskell - 将 (a1,b1) 和 (a2,b2) 映射为 (a1+a2, b1+b2)

转载 作者:行者123 更新时间:2023-12-02 14:29:29 25 4
gpt4 key购买 nike

我记得这是非常基本的,甚至可以通过像 (\a b -> (fst a + fst b, snd a + snd b) ) (1,2) (3,4) 这样的 lambda 来简单地通过模式匹配来完成。 。然而,我认为 Haskell 标准库应该提供一些方法来完成这样的事情。 mappend的定义对于 (a,b)类型为 Monoids 看起来非常相似。但执行以下操作不起作用:

(1,2) `mappend` (3,4)

任何 Haskell 方法可以添加两个 2 元组吗?

最佳答案

数字是幺半群,这不是问题。问题是,有两种不同但同样好用的方式来表示它们是幺半群——加法只是一种,另一种是乘法。因此,标准库决定根本不提供幺半群实例,我认为这是一个很好的决定。

Haskell 允许在 newtype 包装器中打包类型来选择实例,而不会影响底层类型。基类中提供了两个不同的 monoid 实例:

Prelude Data.Monoid> case (Sum 1, Sum 2)<>(Sum 3, Sum 4) of (Sum a, Sum b) -> (a,b)
(4,6)

有点尴尬。有几种方法可以使这个更加简洁(我并不真正推荐其中任何一种;请参阅底部以获得更好的解决方案)。首先,正如 Jon 在评论中所说,如果元组仅包含普通数字文字(如您的示例中所示),则无需将它们显式包装在 Sum 构造函数中,因为有一个实例 Num a => Num (Sum a) 数字文字是多态的,即以下内容:

Prelude Data.Monoid> case (1,2) <> (3,4) of (Sum x, Sum y) -> (x,y)
(4,6)

但是,如果元组元素的类型已经固定...

Prelude Data.Monoid> let [a,b,c,d] = [1,2,3,4] :: [Int]
Prelude Data.Monoid> case (a,b) <> (c,d) of (Sum x, Sum y) -> (x,y) :: (Int,Int)
<interactive>:6:25:
Couldn't match expected type ‘Int’ with actual type ‘Sum Int’
In the pattern: Sum x
In the pattern: (Sum x, Sum y)
In a case alternative: (Sum x, Sum y) -> (x, y) :: (Int, Int)

这里您需要明确应该在哪里进行换行。您仍然可以使用 type-safe coercions 对其进行简要介绍。 ,它允许您一次性将整个容器的所有元素(元组、列表、映射、数组...)包装在新类型中,例如 Sum (并且在 O (1) 时间和空间,这也是一个很大的奖励)。

Prelude Data.Monoid Data.Coerce> case coerce (a,b) <> coerce (c,d) of (Sum x, Sum y) -> (x,y) :: (Int,Int)
(4,6)

使用 Newtype class 可能是一种更简短、更少依赖本地签名的方法。 :

Prelude Data.Monoid> :m +Control.Newtype
Prelude Data.Monoid Control.Newtype> :m +Control.Arrow
Prelude Data.Monoid Control.Newtype Control.Arrow> :simpleprompt
> ala (Sum***Sum) foldMap [(1,2), (3,4)]
(4,6)

...但是,正如我现在相当惊讶地发现的那样,newtype 库并未附带为此所需的元组实例。不过你可以自己定义它:

> :set -XFunctionalDependencies -XUndecidableInstances
> instance (Newtype a α, Newtype b β) => Newtype (a,b) (α,β) where {pack=pack***pack; unpack=unpack***unpack}
<小时/>

如果您确实只需要加法幺半群,我建议您使用专用的进行加法:AdditiveGroup

Prelude Data.AdditiveGroup> (1,2)^+^(3,4)
(4,6)

关于haskell - 将 (a1,b1) 和 (a2,b2) 映射为 (a1+a2, b1+b2),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43667374/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com