问题标签 [invariance]

For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.

0 投票
1 回答
104 浏览

scala - 如何在隐式中实现使用站点差异?

对原始问题的大量修改:现在我预先呈现整个代码,而不显示解释我动机的变体。为混乱道歉。

我需要一个简单的类型类在类型的成员类型之一上实现投影 - 出于本示例的目的,我们让它成为一个简单的转换:

在上面的例子中,很明显投影应该是递归的,Subject子类声明自己的规则。显然,我希望投影实际上是逆变的:

如果Specific不提供自己的投影,Adapter则应使用 for ,最后一个表达式评估为Adapter[Box["F"]]。如果我 declaer 这很好用Projection[-S <: Subject],但问题是我需要投影来保留一些属性,这里表示为Const成员类型:

为了清楚起见,我从上面的代码中删除了这个约束,因为它不会导致问题。

在前面的示例中,编译器将抱怨缺少隐式Projection[Specific],而不尝试向上转换该值。如何使其与使用站点差异编译?

不是存在主义:

我的猜测是,这里的通配符等同于Subject并且没有隐含,除了Projection[Subject]将从未-Xlog-implicits删节问题的编译器日志中搜索(它具有较大的主题层次结构和更多隐含的投影声明)。

然后我尝试了一个中间逆变隐式的技巧,它有时有效:

这看起来很有希望,但不幸的是,编译器和以前完全一样:查看可用的隐式,将类型参数实例化为ProjectionAvailable[Specific, T]并抱怨缺少Projection,而没有利用其逆变性。我尝试了一个变体

除了更明显的错误之外,没有任何真正的区别。我尝试集成ProjectionAvailableinto Projection,但它也没有改变:

我的预感是它可能是可行的,但需要巧妙地手动引导编译器进行类型推断,现在我没有新的探索途径。

0 投票
0 回答
163 浏览

r - mirt 包 R:如何使用 multigroup() 函数创建独立模型


multipleGroup()对 R 中的函数有一些问题,我真的希望有人可以帮助我。
我想首先创建一个独立的、不受约束的模型,其中两个组的所有参数都可能不同,但我收到以下错误消息:

错误:如果没有适当的约束,将无法识别多组模型(组包含缺失的数据模式,其中项目响应已完全省略,或者每个组中的类别数不等于类别总数)

下面你会看到一个运行良好的示例代码(也适用于多头数据),接下来我会展示我的代码和一些关于我的数据的信息。我看不到我的代码中缺少什么......有没有人可以给我一点小费?

示例代码如下:

我的代码产生了上述错误消息,是这样的:

向您显示我的数据的详细信息:

如果您需要任何进一步的信息,请告诉我。非常感谢你!

0 投票
1 回答
191 浏览

arrays - 直观地解释为什么`List`是协变的,而`Array`是不变的?

List[+T]我了解,狗列表也是与直觉完全一致的动物列表。def :: [B >: A](elem: B): List[B]据我了解,我可以将动物( ,不太具体)添加到B狗列表(A,更具体)中,并将返回动物列表。这也符合直觉。所以基本上List是好的。

Array[T]我了解,一组狗不是(不能用来代替a)一组相当违反直觉的动物。一组狗确实也是一组动物,但显然 Scala 不同意。

我希望有人能直观地解释为什么Array是不变的,最好是用狗(或猫)来解释。

为什么数组是不变的,而列表是协变的?但我正在寻找一个不(大量)涉及类型系统的更直观的解释。

为什么 Scala 的不可变 Set 在其类型上不协变有关?

0 投票
2 回答
133 浏览

rust - Rust 函数指针逆变

我很难理解 Rust 中的逆变性。

具体来说:

然而,同样的逻辑不适用于论据。考虑尝试满足:

fn handle_animal(Animal);

fn handle_animal(Cat);

第一个函数可以接受 Dogs,但第二个函数绝对不能。协方差在这里不起作用。但如果我们翻转它,它确实有效!如果我们需要一个可以处理 Cats 的函数,那么一个可以处理任何 Animal 的函数肯定可以正常工作。或者将它与真正的 Rust 联系起来:如果我们需要一个可以处理任何'long至少存在'short.

(来自:https ://doc.rust-lang.org/nomicon/subtyping.html )

这是我无法理解的部分:

或者将它与真正的 Rust 联系起来:如果我们需要一个可以处理任何'long至少存在'short.

如果你在需要'long'的地方传递'short',这不会不起作用吗,这意味着传递的'short'不会活得足够长?

我知道,当谈到生命周期时,如果'long: 'short,那么'long是“短”的子类型(原样'long'short更多),即使考虑到这一点,我仍然在为上述问题苦苦挣扎。

有人可以帮我理解吗?

此外,当谈到方差时,为什么我们说“over”,如:&mut Tis invariant over T'

0 投票
1 回答
606 浏览

typescript - TypeScript 中方差、协方差、逆变和双方差的区别

您能否使用小而简单的 TypeScript 示例解释什么是方差、协方差、逆变和双方差?

[持续更新]

有用的链接:

  1. Oleg Valter的另一个与该主题相关的好答案

  2. Titian-Cernicova-Dragomir对*-riance 的很好解释

  3. 斯蒂芬博耶博客

  4. Scala 文档- 用例子很好的解释

  5. @Titian的回答1

  6. @Titian的回答2

  7. 弗拉德·里斯库蒂亚的博客

  8. 马克·西曼的文章

  9. @jcalz解释

0 投票
0 回答
91 浏览

algorithm - 用 invmap 代替 fmap 和 contramap 的推导

注意:当前问题是 对此问题的后续问题。Daniel Wagner 给出了很好的回答

我试图弄清楚如何为给定类型的 kind派生自然地图* -> *natmap是 的自然映射F如果它等于:

总而言之,Daniel Wagner提出了一种算法,该算法推导fmap给定的仿函数是否是协变的,否则会失败。对于contramap和也可以这样做invmap。他们实施fmap并且contramap

丹尼尔瓦格纳的回答让我思考。必须可以用派生 的单个算法替换三种算法(派生和fmap)。例如:我们推导出来,并且在这样做的同时发现它是协变的。因此,我们可以定义for 。反之亦然:.contramapinvmapinvmapinvmapdata F a = F (a, a)Ffmap f = invmap f undefinedFdata F' = F' ((a, a) -> Int)contramap g = invmap undefined g

是如何invmap派生的?

基本上,我们调整 Daniel Wagner 的算法:

关于上面的一些行的一些评论:

5这个想法是invmap @F (invmap @F' a b) (invmap @F' c d)

  • a处理F出现在协变位置中的协变位置F'
  • bF处理出现在协变位置中的逆变位置F'
  • c处理F出现在逆变位置的协变位置F'
  • d处理F出现在 中的逆变位置的逆变位置F'

IE。ad处理协变位置,而bc处理逆变位置。因此,a = d = f; b = c = g.

6 Id Leafcase 对于逆变函子确实失败了,因为当contramap g被调用时,undefined被放在f's 的位置。Dually:Idleafcase 是唯一f直接用于协变函子的。

为什么它有效?

我认为这个算法之所以有效,是因为一个简单的原因:invmap实际上不必直接使用它的每个参数。此外,当我们尝试将协变处理器用于逆变函子(即 running contramap @Id g x)时,我们会得到一个错误(因为协变处理器undefined)。

基本上,我的想法来自于实施fmapand contramapinvmap就像phantom是实施fmapandcontramap

为什么有趣?

分支会产生一些过热。例如:

除非F和是幻像,否则其中一个案例在检查和F'的整个结构后会失败。有人可能会声称,从两个中选择一个并不能真正归类为过热,并且可以原谅以保持可读性。但是事情变得非常丑陋。我认为以下每种情况都有7个子情况: , , . 这样的代码似乎效率很低。FF'invmapF -> F'F + F'F * F'

所有这些子案例都是由我们对方差的假设产生的。当我们停止invmap只进行派生时,分支就消失了。

问题

这个算法是否产生合法的自然地图?我认为我们无法fmap f = invmap f undefined在合法的情况下证明这一点。相反,我们依赖于我们运行逆变处理器 的事实,即我们遇到逆变位置(逆变位置相同)时,上面的算法就是这种情况。


PS有人认为Invariant接口不如Profunctors,应该避免。但是,如果我的算法确实是正确的,我认为这对这样的类来说是一个很好的用途。

0 投票
5 回答
103 浏览

java - 是否有可能为 Java 数组提供接口?

假设我们想在返回数组的接口中有一个方法,如下所示:

但是数组是非常底层的并且是明确实现的。它们的实现是最终的,不能改变,就像一个最终类。如果此接口中的返回类型已经是数组,则无法返回除数组以外的任何其他内容。因此,最好避免将数组作为返回类型,因为它限制了实现类返回它想要返回的任何内容的自由。所以,我们决定使用java.util.List

但是在实现这个接口时,我们返回一个实际的数组可能非常方便,理论上它确实实现了 List 接口(例如 withaddremovethrowing UnsupportedOperationExceptions):

但这不起作用,因为您不能返回 aB[]而不是List<B>

我想知道低级Java数组是否实现了一个接口(或者甚至可能有一个接口),或者换句话说,可以安全地返回一个数组来代替它。

如果这是可能的,java.util.List也可以扩展它,以便我们可以在幕后交替返回数组或列表。

我已经怀疑这是不可能的,但在计算机的世界里,一切皆有可能,所以谁知道呢。

0 投票
1 回答
60 浏览

rust - 如何分析与方差相关的通用生命周期

Rust Playground链接code snippet 1

以上内容code snippnet 1Rust for Rustacean Ch1 清单 1-11 不同,其中我使用'a替换两个生命周期'a'b,并且此代码无法编译,而我无法说出原因:(

我可以分析一些简单的代码,例如以下代码(来自 Programming Rust Vers 2 page 120):

Rust Playground链接code snippet 2

我分别表示xyr、和'x的 生命周期:'y'r

'X 'y '
线路:从 8 到 18 线路:从 11 到 16 线路:从 9 到 17

当在线实例化s13,我们正在要求'x:'a ('x outlives 'a) 'y:'a,而当分配r = s.x发生在队列中时14,我们正在要求'a:'r。然而,这是不可能的,因为'y:'a冲突'a:'r(见上表,'y比 短'r),因此 rustc 无法找到'a满足这些冲突条件的通用生命周期的确定性生命周期。

更新:我期待 code snippet 1与上述类似的分析过程,或者遇到生命周期问题时的一般推理方法:)

我已经阅读了这篇文章,了解了一些基本概念variance,例如covariance invariancecontravariance。而且我有点认为我的问题与此有关,但不知道如何使用它来分析code snippet 1

顺便说一句,我仍然想知道掌握lifetimerust 的正确位置是什么。如果你知道,请告诉我:),我很感激。

如果您发现我的问题不正常,请随时指出:)