具有RankNTypes的newtype

17
如果我想声明一个 newtype,以便该值的类型受限于必须具有某个类型类的实例,似乎可以使用以下方法:
```haskell newtype MyType a = MyType {unMyType :: a} deriving (SomeTypeclass) ```
```haskell newtype MyType a = MyType {unMyType :: a} deriving (SomeTypeclass) ```
{-# LANGUAGE RankNTypes #-}

newtype ShowBox = ShowBox (forall a. Show a => a)

GHC可以很好地编译它,但是当我尝试使用ShowBox时,出现了问题。


ShowBox "hello"

我遇到了编译器错误。

<interactive>:1:18:
    Could not deduce (a ~ [Char])
    from the context (Show a)
      bound by a type expected by the context: Show a => a
      at <interactive>:1:10-24
      `a' is a rigid type variable bound by
          a type expected by the context: Show a => a at <interactive>:1:10
    In the first argument of `ShowBox', namely `"hello"'
    In the expression: ShowBox "hello"
    In an equation for `a': a = ShowBox "hello"

有没有办法让这个工作?


这个量化是否意味着你认为的意思?我真的不确定,我自己也不确定。我在想它可能意味着 ShowBox 只能应用于精确类型为 Show a => a 的值。我非常想知道这个问题的答案。 - Daniel Pratt
2个回答

19

你向编译器承诺,在ShowBox中放置的值将具有类型forall a. Show a => a。这种类型只有一种可能的值,即_|_。我认为你可能想要存在类型,它看起来相似,但意义非常不同。

{-# LANGUAGE ExistentialQuantification #-}

data ShowBox = forall a. Show a => ShowBox a

这必须使用 data 来完成,而不是 newtype。在此情况下,模式匹配构造函数是将 Show 实例引入范围的原因。由于 newtype 没有运行时表示,因此它们没有存储多态证明的存在量化意味着的位置。


3
换句话说,@user1279710的ShowBox中要放入能够是Show任何实例,但他尝试放入了一个特定的Show实例。(暂停主题切换)在这种情况下,类型为forall a. Show a => a的唯一值是_|_,因为Show类型类不包括构造实例类型值的任何方法,只包括消费它们的方法。 - Daniel Wagner
3
编译器如果能给出警告,比如“无用的数据声明:Show a => a:只能由_|_占位符填充”,那就太好了。 - Dan Burton
好的,我明白了。我希望有一种不需要装箱就能实现这个的方法,但我看到这并不是真正可能的。谢谢。 - purefn
1
@purefn:装箱很重要。对于有类限制的存在类型,在装箱实际上会将类字典存储在运行时。这就是使用该类所必需的,而不仅仅是在构造时受到限制。 - Carl
3
请注意,这个 ShowBox 本质上与 String 相同。在许多情况下,存在类型可以简化为更简单、具体的类型;寻找这些机会,它们可能会简化您的代码库。 - luqui

7

好的,你的Show构造函数具有以下类型:

Show :: (forall a. Show a => a) -> ShowBox

您正在尝试将此函数应用于类型[Char],该类型不属于forall a. Show a => a类型,因为a是“Skolem变量”,只能在非常严格的规则下与另一种类型统一(其他人可以比我更好地解释这一点)。
您确定以下内容不是您想要的内容(除了data vs. newtype)吗? 为什么要在构造函数中限定forall的范围?
-- Show :: Show a => a -> ShowBox
data ShowBox = forall a. Show a => Show a

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接