5

考虑这种类型:

newtype Ap f a = Ap (f a)
instance (Applicative f, Num a) => Num (Ap f a) where
  (+)         = liftA2 (+)
  (*)         = liftA2 (*)
  negate      = fmap negate
  fromInteger = pure . fromInteger
  abs         = fmap abs
  signum      = fmap signum

f该实例合法需要满足什么条件?显然,仅仅作为一个合法Applicative的是不够的(例如,与when isx + negate x不同,即使是一个合法的)。我的猜测是,成为一个可表示的函子既是必要的又是充分的。不过,我不确定如何证明这一点(或者如果它是错误的,则找到一个反例)。fromInteger 0xAp NothingMaybeApplicativef

为了参考起见,以下是文档建议Num法律

-- Associativity of (+)
(x + y) + z = x + (y + z)

-- Commutativity of (+)
x + y = y + x

-- fromInteger 0 is the additive identity
x + fromInteger 0 = x

-- negate gives the additive inverse
x + negate x = fromInteger 0

-- Associativity of (*)
(x * y) * z = x * (y * z)

-- fromInteger 1 is the multiplicative identity
x * fromInteger 1 = x
fromInteger 1 * x = x

-- Distributivity of (*) with respect to (+)
a * (b + c) = (a * b) + (a * c)
(b + c) * a = (b * a) + (c * a)
4

2 回答 2

6

这种结构称为代数,它是一个带有乘积的向量空间。将向量空间实现为可表示的函子是一种众所周知的模式。这就是linear图书馆的全部基础。

代数是微不足道的ring(通过忘记标量),这是每个人都可以就Num该类实际描述的内容达成一致的唯一内容。从这个意义上说,是的,Representable这就是我们所需要的。具体来说,您正在利用的是用它们的基础扩展替换抽象向量,即您基本上将所有内容简化为

instance Num a => Num (r -> a) where
  fromInteger = const . fromInteger
  f + g = \e -> f e + g e
  f * g = \e -> f e * g e
  negate f = negate . f
  abs f = abs . f
  signum f = signum . f

然后可以与 一起使用r ~ Rep f,因为类型Rep f -> af a.

我个人不喜欢这些。特别是etc. 的Num实例V2在背后是一种痛苦,因为1 :: V2 Double ≡ V2 1 1如果您正在处理应该与旋转无关的图表,那么 eg 在几何上没有任何意义。看,任何有限维向量空间可以用可表示的函子来实现,但这需要选择一个任意的基。但这有点像为文本编辑器选择任意字符编码,然后以在公共界面中完全公开的方式对其进行硬烘焙。这是糟糕的设计。仅仅因为你可以并不意味着你应该。

此外,许多实际有用的向量空间不能用可表示的仿函数来实现,或者这种实现可能非常不切实际。我在这里谈论的是稀疏向量,或高效的未装箱和/或分布式存储,或(个人最喜欢的)无限维函数空间。

因此,我建议将Num课程保留为明确的数字,并根据您的实际需要明确调用其他所有内容。我的free-vector-spaceslinearmap-category包试图以一种有原则且强大的方式来做到这一点,建立在vector-space中简单而安全的类的基础上。

于 2022-01-28T19:17:55.737 回答
3

f该实例合法需要满足哪些条件?

为了勾勒一个论点,我们可以首先关注Ap f ()位于应用程序下的影响幺半群(如果你愿意的话)。为了保持左分布,我们需要影响幺半群是左自分布的(即u <> (v <> w) = (u <> v) <> (u <> w)),并且类似地对于右分布。此外,如果一个幺半群既是左自分配的又是右自分配的,则它必须既是可交换的又是幂等的。这已经是一个很大的限制,尽管还不足以排除Maybe(这是一个幂等的、可交换的应用程序)。既然如此,使用您的提示并查看加法逆定律是有意义的:

x + negate x = fromInteger 0
-- Substitute the instance implementations:
liftA2 (+) x (negate <$> x) = pure (fromInteger 0)
-- (&*&) = liftA2 (,)
(\(a, b) -> a + negate b) <$> (x &*& x) = pure (fromInteger 0)

特别是,(() <$)在两边使用给我们:

() <$ (x &*& x) = pure ()

回到影响幺半群的观点,这相当于u <> u = mempty. 由于我们之前已经确定效果幺半群必须是幂等的,u <> u = u. 因此,u = mempty; 也就是说,只有一种可能Ap f ()

至于其他的规律,恒等律和结合律应该遵循应用律,而交换律的(+)大概需要f是可交换的应用律...

liftA2 g u v = liftA2 (flip g) v u

...这比仅要求Ap f ()我之前提到的可交换性要强一些(请参阅Select有关说明)。

因此,为了使Num (Ap f a)实例合法,我们似乎至少需要它f是一个可交换的应用程序,并且只有一个f ()值。虽然这个论点还不是完全无懈可击,但这些要求确实让人想起可表示的函子。

于 2022-01-29T11:31:48.893 回答