Haskell 为什么';数据的应用实例。向量对角化其结果?

Haskell 为什么';数据的应用实例。向量对角化其结果?,haskell,Haskell,所以我想在几个大小相等的向量上建立一个函数。嗯,Applicative λ➔ let f x y z = x * y + z λ➔ λ➔ let va = V.fromList [10, 20, 30] λ➔ let vb = V.fromList [2, 5, 3] λ➔ let vc = V.fromList [1, 2, 3] λ➔ λ➔ f <$> va <*> vb <*> vc fromList [21,22,23,51,52,53,31,32,3

所以我想在几个大小相等的向量上建立一个函数。嗯,
Applicative

λ➔ let f x y z = x * y + z
λ➔
λ➔ let va = V.fromList [10, 20, 30]
λ➔ let vb = V.fromList [2, 5, 3]
λ➔ let vc = V.fromList [1, 2, 3]
λ➔
λ➔ f <$> va <*> vb <*> vc
fromList [21,22,23,51,52,53,31,32,33,41,42,43,101,102,103,61,62,63,61,62,63,151,152,153,91,92,93]
它只是列举了所有的参数组合。对于
()
,这看起来是一个非常糟糕的定义,因为结果是组合爆炸的

相反,它可以对结果进行对角化以生成
[11,22,33]
,类似于这样:

instance Applicative Vector where
    pure = repeat
    fs <*> xs = zipWith ($) fs xs
实例应用程序向量,其中
纯=重复
fs xs=zipWith($)fs xs
这仍然使有效的
应用程序
实例可用。在我看来,这更有用

除了明显的疏忽之外,还有什么理由让这个实例以这种方式编写

此外,对于进一步行动的经验丰富的建议也表示感谢



*编辑:更正之前的
pure=single

这不仅仅是疏忽。为了使
Applicative
实例正确,我们需要一个
pure
的实现,它的行为就像一个无限长的向量,所有的元素都是相同的。(而且由于API提供扫描,因此库还需要能够具有类似于任意无限长向量的值。)当前实现出于性能原因使用数组;由于显而易见的原因,不能有一个无限大小的数组


在zippy应用程序流行之前,您可以用我们以前的方式实现您想要的。有一些函数专门用于指定要压缩在一起的参数的数量,以及通常的名称。

这不仅仅是疏忽。为了使
Applicative
实例正确,我们需要一个
pure
的实现,它的行为就像一个无限长的向量,所有的元素都是相同的。(而且由于API提供扫描,因此库还需要能够具有类似于任意无限长向量的值。)当前实现出于性能原因使用数组;由于显而易见的原因,不能有一个无限大小的数组


在zippy应用程序流行之前,您可以用我们以前的方式实现您想要的。有一些函数专门针对要压缩在一起的参数的数量,使用通常的名称。

我只使用
Vector.zipWith

我从使用
Vector
中学到的一件事是,您通常希望坚持库的操作,避免使用
Functor
/
Applicative
/
Monad
实例。为什么?因为库的一些类型不能支持类型类。例如,如果您使用
Data.Vector.Vector
Functor
实例编写了一组代码,然后决定使用
Data.Vector.unbox.Vector
,则必须将所有
fmap
更改为
Data.Vector.unbox.map
,由于未绑定向量不是
函子
实例,因此元素类型带有
Unbox
约束


不幸的是,这只是一个长期未解决的Haskell问题的例子(当类型需要对类型参数进行约束时,无法生成
*->*
类的实例)。

我只会使用
Vector.zipWith

我从使用
Vector
中学到的一件事是,您通常希望坚持库的操作,避免使用
Functor
/
Applicative
/
Monad
实例。为什么?因为库的一些类型不能支持类型类。例如,如果您使用
Data.Vector.Vector
Functor
实例编写了一组代码,然后决定使用
Data.Vector.unbox.Vector
,则必须将所有
fmap
更改为
Data.Vector.unbox.map
,由于未绑定向量不是
函子
实例,因此元素类型带有
Unbox
约束

不幸的是,这只是一个长期未解决的Haskell问题的示例(当类型需要对类型参数进行约束时,无法生成
*->*
类的实例)。

您可以生成一个类型:

数据对角化向量a=对角化向量(a(向量a))

为此编写应用程序实例很容易,它将所有内容都转发给Right,并将left应用于Right的每个元素或另一个单数left。左表示可以认为占据所有点的纯值

这将很容易满足您的需求,您可以根据自己的喜好进行定制和优化。

您可以制作一个类型:

数据对角化向量a=对角化向量(a(向量a))

为此编写应用程序实例很容易,它将所有内容都转发给Right,并将left应用于Right的每个元素或另一个单数left。左表示可以认为占据所有点的纯值


这将很容易满足您的需求,您可以根据自己的意愿对其进行定制和优化。

这不是一个合法的应用实例
\x->pure id x
id
不同。查看
ZipList
的应用程序实例,了解相关示例。我支持@Carl,但值得指出的是,可以为来自的
类型编写正确的
操作。我只想使用
Vector.zipWith
。@ulidtko:您在Idris中使用的向量类型是否将向量的大小编码到类型本身中?基本上,问题在于,对于正确的实现,(a)所有向量需要具有相同的长度,(b)纯需要知道该长度是多少。因此,如果您有一个独立类型大小的向量类型,那么它确实支持一个zippy
Applicative
实例
instance Applicative Vector where
    pure = repeat
    fs <*> xs = zipWith ($) fs xs