【问题标题】:Deriving in newtype with more type variables派生具有更多类型变量的 newtype
【发布时间】:2016-09-09 18:39:56
【问题描述】:
newtype MyNewtype1 f v = MyNewtype1 { getVal1 :: f v } deriving Eq -- OK
newtype MyNewtype2 f maybe v = MyNewtype2 { getVal2 :: f (maybe v) } deriving Eq --OK
newtype MyNewtype3 f v = MyNewtype3 { getVal3 :: f (Maybe v) } --  OK
newtype MyNewtype4 f v = MyNewtype4 { getVal4 :: f (Maybe v) } deriving Eq --NOT OK

我有这些新类型。前三个按预期工作,但第四个给出:

    • No instance for (Eq (f (Maybe v)))
        arising from the 'deriving' clause of a data type declaration
      Possible fix:
        use a standalone 'deriving instance' declaration,
          so you can specify the instance context yourself
    • When deriving the instance for (Eq (MyNewtype4 f v))

我不明白问题出在哪里。在我看来,第二个新类型严格来说更通用,因此必须遇到同样的问题。那么如果MyNewtype2 可以推导出Eq,为什么MyNewtype2 不能呢?这可能是最让我困惑的地方。有人可以向我解释一下吗?另外,如果我想要这样的新类型,首选的解决方案是什么?

【问题讨论】:

    标签: haskell deriving newtype


    【解决方案1】:

    我不知道为什么 2 有效,但 4 无效。可能与灵活的上下文有关(我不太了解,无法解释)。

    回答第二个问题...如果您想要像 GHC 建议的那样的新类型,首选的解决方案是:使用独立的派生实例。

    {-# LANGUAGE StandaloneDeriving, FlexibleContexts, UndecidableInstances #-}
    
    newtype MyNewtype4 f v = MyNewtype4 { getVal4 :: f (Maybe v) }
    deriving instance (Eq (f (Maybe v))) => Eq (MyNewtype4 f v)
    

    【讨论】:

    • 谢谢,我不知道独立派生语法。我仍然感兴趣,为什么 2 有效。
    • 文档中的特定规则说“规则是这样的:推断的实例上下文中的每个约束必须只包含类型变量,不能重复。”显然Eq (f (maybe v)) 符合条件`。
    • @AlexeyRomanov,这似乎......令人惊讶。我认为FlexibleContexts 是一个非侵入式扩展,它真的只是简化了一切,我是否正确?或者它是否会产生一些不幸的后果,例如(某些方面)FlexibleInstances
    • 我没有删除我的答案,因为我发现为什么 4 是不允许的(我认为)。
    【解决方案2】:

    【讨论】:

    • 好的,但是即使使用 -XUndecidableInstances 也会引发相同错误的原因是什么?
    • 那是我一开始没有引用的那句话:“无论标志如何,都适用此规则”。他们认为它足够不安全,应该明确地出现在代码中,这样如果你遇到终止问题,你可以更容易地找到它。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-05-22
    • 1970-01-01
    • 2017-03-19
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多