问题标签 [overlapping-instances]
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.
haskell - Show 的重叠实例
假设我们有以下内容:
使用此代码,ghc 抱怨:
我可以理解它认为类型a
可以派生Show
或派生ListContainer
,这可能会导致Show
.
我们如何避免这种情况?
我知道存在一个 function showList
,但它的签名有点陌生。我已经有一个函数,我打算用来显示某些列表,它String
直接返回。
haskell - 为什么使用具有重叠实例的类型类的此函数在 GHCi 中表现不同?
背景
我在 Haskell (GHC 8.6.3) 中编写了以下代码:
这段代码背后的想法是产生一个可变参数的函数,它接受它的参数并将它们打包到一个异构列表中。
例如,以下
产生列表Cons "a" (Cons "b" nil)
。
问题
一般来说,我想fpack
通过id
作为f
参数传递来调用(如上),所以我希望将以下函数定义为简写:
如果我将上面的程序加载到 GHCi 并执行上面的行,pack 会根据需要定义,并且它的类型(由 给出:t
)是FPack (a -> a) r => r
. 所以我在我的程序中定义了这样的函数:
但这在将所述程序加载到 GHCi 时会出现以下错误:
这引出了我的问题。为什么这个函数在 GHCi 中定义时有效,但在程序中定义时无效?有没有办法让我在程序中正常工作?如果是这样,怎么做?
我的想法
根据我对 GHC 和 Haskell 的了解,这个错误来自于pack
可以解决两个重叠实例中的任何一个的事实,这会困扰 GHC。但是,我认为该AllowAmbiguousTypes
选项应该通过将实例选择推迟到最终调用站点来解决该问题。不幸的是,这显然还不够。我很好奇为什么,但我更好奇为什么 GHCi 在它的 REPL 循环中接受这个定义,但是当它在程序中时它不接受它。
切线
我有另一个关于这个程序的问题,它与这个问题的主旨没有直接关系,但我认为在这里问它可能是明智的,而不是就同一个程序创建另一个问题。
如上面的示例所示,即
我必须提供一个明确的类型签名fpack
才能使其按需要工作。如果我不提供(即只调用fpack id "a" "b"
),GHCi 会产生以下错误:
有什么办法可以改变的定义fpack
让 GHC 推断出正确的类型签名?
haskell - 递归列表变换中重叠实例的行为
在我的递归列表转换中,重叠实例的优先级没有按预期进行。
我正在尝试创建一个对任意深度的嵌套列表进行操作的转置函数。目标是有两个函数,一个可以将“最高维度”向下转换为“最低维度”,即维度为 [a, b, c] 的嵌套列表将转换为维度为 [ b, c, a] 和一个相反的,[a, b, c] 到 [c, a, b]。
我的意图是第一个实例应用于所有嵌套列表,第二个实例应用于其他所有内容。
以下是一些测试示例,“ref”表示函数的预期行为
然而,参考和测试的结果是不同的,例如:
我没有太多使用重叠实例的经验,所以我不确定如何选择实例。对我来说,似乎转置只发生在第一个“层”中,之后使用第二个实例(id)。这有效地把它变成了正常的转置,这不是很有趣。
haskell - 重叠多参数实例和实例特异性
既不编译aretheyreallyeq
也不aretheyeq
编译,但是 for 的错误对aretheyreallyeq
我来说是有意义的,并且还告诉我不aretheyeq
应该给出错误:GHCi 建议的可能 for EqM
in的实例之一aretheyeq
应该是不可能的,因为aretheyreallyeq
. 这是怎么回事?
关键是,GHCi 坚持认为 的两个实例EqM
都适用于aretheyeq
. But a1
is of typea
和b2
is of type b
,所以为了使第一个实例适用,它必须具有类型a
和b
统一。
但这应该是不可能的,因为它们在函数签名处被声明为类型变量(也就是说,使用第一个EqM
实例会导致函数为 type Either a a -> Either a a -> Bool
,并且aretheyreallyeq
告诉我 GHCi 不允许这样做(无论如何都是我所期望的)。
我是否遗漏了什么,或者这是如何检查具有多参数类型类的重叠实例的错误?
我在想这可能与这样一个事实有关,a
并且b
以后可以进一步实例化到它们相等的点, outside aretheyeq
,然后第一个实例是有效的?但对于aretheyreallyeq
. 唯一的区别是,如果他们不统一,我们可以选择aretheyeq
,但我们没有aretheyreallyeq
。在任何情况下,Haskell 没有动态调度有很多好的和明显的原因,所以有什么害怕提交实例总是有效的,无论以后a
是否b
统一也许有某种方法可以在以某种方式调用函数时选择实例?
值得注意的是,如果我删除第二个实例,那么该函数显然仍然无法编译,说明找不到实例EqM a b
。因此,如果我没有那个实例,那么没有一个有效,但是当那个有效时,突然另一个也有效并且我有重叠?几英里外的我闻起来像虫子。
haskell - Multi-way FunDeps 和重叠实例的一致性:(为什么)这行得通?
这是旧栗子的变种。我写它期望它不起作用,但它确实起作用了。还是很狡猾?(在 GHC 8.6.5 时。)
传统上, class 上只有两个 FunDeps AddNat
,第二个实例是
Functional dependencies conflict between instance declarations:
如果有 FunDep ,该实例将被拒绝b c -> a
。事实上,该OVERLAPPABLE
实例正在利用 GHC 的虚假 FunDep 一致性检查。
但是没有那个 FunDep,subNat
就无法从参数中推断出它的结果:Ambiguous type variable 'a0'
. 我猜我的测试有效,因为参数的类型是subNat
完全已知的。如果它们是部分已知的,类型改进将陷入无法拒绝ZNat b b
实例的困境。
Oleg Kiselyov 的 ftp 站点曾经有一个类用于 3 向改进添加自然,但它有一个复杂的辅助超类约束和辅助实例的复杂巢穴,基本上重复了中心类。我所做的似乎太简单了。哪里会出错?
haskell - 对“冲突的家庭实例声明”感到困惑
我收到一个我不太理解的冲突家庭实例错误:
结果是
n
并不比[a]
因为Num n
实例头中的约束更通用。这些对我来说似乎并不矛盾。Num
如果我实施for以后可能会出现冲突的问题[a]
吗?如果是这样,任何两个实例都不会存在这种潜在的冲突吗?
功能依赖会以类型族不允许的方式允许这样做吗?
完整代码如下:
haskell - Haskell - 重叠实例和转换类型类
我正在编写代码以通过数学逻辑中的定义来实现扩展。
它接受语言及其扩展的描述,并输出一个新的 haskell 文件,该文件会将高级语言解析为低级语言。当然,如果我能把C语言变成B语言,B语言变成A语言,那么通过作曲我就可以把C语言变成A语言……然而……
这是我面临的问题的一个最小示例:
直觉上, 没有什么问题instance (ToB a) => ToA a
,但编译器不喜欢它。代码按原样编译,但在用ToA C
注释版本替换显式实例后,我收到以下错误:
当然,我不害怕语言扩展,所以我按照我的指示去做并添加了 FlexibleInstances,尽管我认为它在这里没有帮助。完成此操作后,我被告知尝试 UndecidableInstances ......这就是线索停止的地方。我仍然收到类型错误,但我不确定该怎么做。
这个错误信息让我特别困惑,因为我只有一个ToA B
. 如果这个错误B
本身是 的一个实例ToB
,比如通过设置convertToB = id
. 当然,这里不是这样的……
我应该如何正确处理这个问题?提前致谢!^_^
haskell - 多个重叠实例的交互
模块Type.hs
定义了谐音newtype
,只导出其类型构造函数,不导出值构造函数,避免暴露细节;它还提供了一个构造函数makeType
来平衡缺少值ctor。为什么我需要将 a 包装成String
一个新类型?因为我希望它不仅仅是一个String
; 在我的具体情况下,Type
实际上被称为Line
,并且对应于makeType
强制它只包含一个\n
,作为最后一个字符。Anewtype
对我来说似乎是最明显的选择。如果不是这样,请原谅我:我正在学习。
为了以Type
我喜欢的方式显示类型的值(例如,给定我的实际用例Line
,我可能想\n
用一个漂亮的 unicode 字符或序列<NL>
或其他方式表示),我创建了另一个模块TypeShow.hs
,我稍后(在尝试做我所描述的事情时)我通过添加一些编译指示进行了编辑。为什么是另一个模块?因为我猜某些东西在内部的运作方式和我在屏幕上展示它的方式是两个独立的方面。我错了吗?
除了这对模块(描述 的核心Type
,以及它应该如何显示)之外,我还创建了其他类似的对Type1
/ Type1Show
,Type2
/ Type2Show
,它们都包裹 aString
来表示和显示其他类似String
实体。
Type
由于其他原因,我还需要另一种包装可选值的类型,它可以是Type1
, 或任何其他类型,所以我编写了这个模块
(实际上Wrapper
实际上包装了多个Type
值,但我会避免提供更多必要的细节;如果以下内容很愚蠢,因为我只在 中包装了一个Type
值Wrapper
,那么请考虑它实际上包装了多个值。)同样,在这里我试图隐藏细节,Wrapper
同时提供makeWrapper
制作一个,并getInside
对其内部进行“受控”访问。
我也想在屏幕上显示这个,所以我创建了一个相应的WrapperShow.hs
模块,所以它Wrapper
的show
方法依赖于内容的show
方法。
然而,此时,当类型a
为 a时Maybe Type
,我想显示Wrapper
打印空字符串的内容,而不是Nothing
,或 ; 的内容Just
。因此,我写了instance Show (Maybe Type)
我在上面评论过的内容。
鉴于此,Type "hello"
andJust $ Type "hello"
都正确显示为Type
,但Wrapper $ Just $ Type "hello"
显示为Just Type
,就像它使用Maybe
的原始实例一样,无论对于( )Show
中的这种特定类型,我已经自定义了实例。Maybe
Type
Show
haskell - 有没有一种方法可以多态地提升具有 monad 类型变量的类的实例,而不会重叠实例?
这个问题可以认为是后续问题
将具有“MonadIO”类型变量的类实例提升到转换后的 monad
其中提供了一个应用程序的示例,该示例将在何处使用。
这个想法是一个类型类
存在,在不同的 monad 中有基本实例
. 我想要的是一种将任何实例提升到自身或在变压器堆栈中更高的方法,就像liftIO
为IO
. 我最初的想法是定义一个提升实例
然而,当应用多个转换器时,这会产生重叠实例的问题,就像lift
多态一样,并且可以替换为,例如lift . lift
.
建议改用类似的默认实例,
然后可以用来声明提升实例
. 这可行,但是需要为每个基本实例声明提升实例,所以我很好奇;有没有其他方法可以在不使用重叠实例的情况下解决这个问题?
haskell - 如何将重叠编译指示应用于派生实例
Pragma OverlappingInstances 在 GHC 中被弃用了一段时间,而 OVERLAPPING pragma 是它的替代品。
虽然这不是 Haskell 中定义类实例的唯一方法。我无法通过派生来定义重叠实例,并避免对已弃用的 OverlappingInstances 发出讨厌的警告。
以下情况均无效: