问题标签 [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.
scala - 如何在隐式中实现使用站点差异?
对原始问题的大量修改:现在我预先呈现整个代码,而不显示解释我动机的变体。为混乱道歉。
我需要一个简单的类型类在类型的成员类型之一上实现投影 - 出于本示例的目的,我们让它成为一个简单的转换:
在上面的例子中,很明显投影应该是递归的,Subject
子类声明自己的规则。显然,我希望投影实际上是逆变的:
如果Specific
不提供自己的投影,Adapter
则应使用 for ,最后一个表达式评估为Adapter[Box["F"]]
。如果我 declaer 这很好用Projection[-S <: Subject]
,但问题是我需要投影来保留一些属性,这里表示为Const
成员类型:
为了清楚起见,我从上面的代码中删除了这个约束,因为它不会导致问题。
在前面的示例中,编译器将抱怨缺少隐式Projection[Specific]
,而不尝试向上转换该值。如何使其与使用站点差异编译?
不是存在主义:
我的猜测是,这里的通配符等同于Subject
并且没有隐含,除了Projection[Subject]
将从未-Xlog-implicits
删节问题的编译器日志中搜索(它具有较大的主题层次结构和更多隐含的投影声明)。
然后我尝试了一个中间逆变隐式的技巧,它有时有效:
这看起来很有希望,但不幸的是,编译器和以前完全一样:查看可用的隐式,将类型参数实例化为ProjectionAvailable[Specific, T]
并抱怨缺少Projection
,而没有利用其逆变性。我尝试了一个变体
除了更明显的错误之外,没有任何真正的区别。我尝试集成ProjectionAvailable
into Projection
,但它也没有改变:
我的预感是它可能是可行的,但需要巧妙地手动引导编译器进行类型推断,现在我没有新的探索途径。
r - mirt 包 R:如何使用 multigroup() 函数创建独立模型
我multipleGroup()
对 R 中的函数有一些问题,我真的希望有人可以帮助我。
我想首先创建一个独立的、不受约束的模型,其中两个组的所有参数都可能不同,但我收到以下错误消息:
错误:如果没有适当的约束,将无法识别多组模型(组包含缺失的数据模式,其中项目响应已完全省略,或者每个组中的类别数不等于类别总数)
下面你会看到一个运行良好的示例代码(也适用于多头数据),接下来我会展示我的代码和一些关于我的数据的信息。我看不到我的代码中缺少什么......有没有人可以给我一点小费?
示例代码如下:
我的代码产生了上述错误消息,是这样的:
向您显示我的数据的详细信息:
如果您需要任何进一步的信息,请告诉我。非常感谢你!
arrays - 直观地解释为什么`List`是协变的,而`Array`是不变的?
据List[+T]
我了解,狗列表也是与直觉完全一致的动物列表。def :: [B >: A](elem: B): List[B]
据我了解,我可以将动物( ,不太具体)添加到B
狗列表(A
,更具体)中,并将返回动物列表。这也符合直觉。所以基本上List
是好的。
据Array[T]
我了解,一组狗不是(不能用来代替a)一组相当违反直觉的动物。一组狗确实也是一组动物,但显然 Scala 不同意。
我希望有人能直观地解释为什么Array
是不变的,最好是用狗(或猫)来解释。
为什么数组是不变的,而列表是协变的?但我正在寻找一个不(大量)涉及类型系统的更直观的解释。
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 T
is invariant over T'
?
typescript - TypeScript 中方差、协方差、逆变和双方差的区别
您能否使用小而简单的 TypeScript 示例解释什么是方差、协方差、逆变和双方差?
[持续更新]
有用的链接:
Oleg Valter的另一个与该主题相关的好答案
Titian-Cernicova-Dragomir对*-riance 的很好解释
斯蒂芬博耶博客
Scala 文档- 用例子很好的解释
@Titian的回答1
@Titian的回答2
马克·西曼的文章
@jcalz解释
algorithm - 用 invmap 代替 fmap 和 contramap 的推导
注意:当前问题是 对此问题的后续问题。Daniel Wagner 给出了很好的回答。
我试图弄清楚如何为给定类型的 kind派生自然地图* -> *
。natmap
是 的自然映射,F
如果它等于:
fmap :: (a -> b) -> F a -> F b
在协变的情况下F
,contramap :: (b -> a) -> F a -> F b
在逆变的情况下F
,invmap :: (a -> b) -> (b -> a) -> F a -> F b
在不变量的情况下F
,- 或者
phantom :: F a -> F b
在幻影的情况下F
。
总而言之,Daniel Wagner提出了一种算法,该算法推导fmap
给定的仿函数是否是协变的,否则会失败。对于contramap
和也可以这样做invmap
。他们实施fmap
并且contramap
:
丹尼尔瓦格纳的回答让我思考。必须可以用派生 的单个算法替换三种算法(派生和fmap
)。例如:我们推导出来,并且在这样做的同时发现它是协变的。因此,我们可以定义for 。反之亦然:.contramap
invmap
invmap
invmap
data F a = F (a, a)
F
fmap f = invmap f undefined
F
data 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'
,b
F
处理出现在协变位置中的逆变位置F'
,c
处理F
出现在逆变位置的协变位置F'
,d
处理F
出现在 中的逆变位置的逆变位置F'
。
IE。a
和d
处理协变位置,而b
和c
处理逆变位置。因此,a = d = f
; b = c = g
.
6 Id
Leafcase 对于逆变函子确实失败了,因为当contramap g
被调用时,undefined
被放在f
's 的位置。Dually:Id
leafcase 是唯一f
直接用于协变函子的。
为什么它有效?
我认为这个算法之所以有效,是因为一个简单的原因:invmap
实际上不必直接使用它的每个参数。此外,当我们尝试将协变处理器用于逆变函子(即 running contramap @Id g x
)时,我们会得到一个错误(因为协变处理器是undefined
)。
基本上,我的想法来自于实施fmap
and contramap
,invmap
就像phantom
是实施fmap
andcontramap
。
为什么有趣?
分支会产生一些过热。例如:
除非F
和是幻像,否则其中一个案例在检查和F'
的整个结构后会失败。有人可能会声称,从两个中选择一个并不能真正归类为过热,并且可以原谅以保持可读性。但是事情变得非常丑陋。我认为以下每种情况都有7个子情况: , , . 这样的代码似乎效率很低。F
F'
invmap
F -> F'
F + F'
F * F'
所有这些子案例都是由我们对方差的假设产生的。当我们停止invmap
只进行派生时,分支就消失了。
问题
这个算法是否产生合法的自然地图?我认为我们无法fmap f = invmap f undefined
在合法的情况下证明这一点。相反,我们依赖于我们运行逆变处理器 的事实,即当我们遇到逆变位置(逆变位置相同)时,上面的算法就是这种情况。
PS有人认为Invariant
接口不如Profunctor
s,应该避免。但是,如果我的算法确实是正确的,我认为这对这样的类来说是一个很好的用途。
java - 是否有可能为 Java 数组提供接口?
假设我们想在返回数组的接口中有一个方法,如下所示:
但是数组是非常底层的并且是明确实现的。它们的实现是最终的,不能改变,就像一个最终类。如果此接口中的返回类型已经是数组,则无法返回除数组以外的任何其他内容。因此,最好避免将数组作为返回类型,因为它限制了实现类返回它想要返回的任何内容的自由。所以,我们决定使用java.util.List
:
但是在实现这个接口时,我们返回一个实际的数组可能非常方便,理论上它确实实现了 List 接口(例如 withadd
和remove
throwing UnsupportedOperationException
s):
但这不起作用,因为您不能返回 aB[]
而不是List<B>
。
我想知道低级Java数组是否实现了一个接口(或者甚至可能有一个接口),或者换句话说,可以安全地返回一个数组来代替它。
如果这是可能的,java.util.List
也可以扩展它,以便我们可以在幕后交替返回数组或列表。
我已经怀疑这是不可能的,但在计算机的世界里,一切皆有可能,所以谁知道呢。
rust - 如何分析与方差相关的通用生命周期
Rust Playground链接
code snippet 1
以上内容code snippnet 1
与Rust for Rustacean Ch1 清单 1-11 不同,其中我使用'a
替换两个生命周期'a
和'b
,并且此代码无法编译,而我无法说出原因:(
我可以分析一些简单的代码,例如以下代码(来自 Programming Rust Vers 2 page 120):
Rust Playground链接
code snippet 2
我分别表示x
、y
和r
、和'x
的 生命周期:'y
'r
'X | 'y | ' |
---|---|---|
线路:从 8 到 18 | 线路:从 11 到 16 | 线路:从 9 到 17 |
当在线实例化s
时13
,我们正在要求'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
invariance
和contravariance
。而且我有点认为我的问题与此有关,但不知道如何使用它来分析code snippet 1
。
顺便说一句,我仍然想知道掌握lifetime
rust 的正确位置是什么。如果你知道,请告诉我:),我很感激。
如果您发现我的问题不正常,请随时指出:)