具有RankNTypes的newtype

pur*_*efn 17 haskell higher-rank-types newtype

如果我想声明一个newtype类型的类型被约束为具有类型类的实例,我似乎可以这样做:

{-# LANGUAGE RankNTypes #-}

newtype ShowBox = ShowBox (forall a. Show a => a)
Run Code Online (Sandbox Code Playgroud)

GHC编译就好了,但是当我尝试并实际使用ShowBox

ShowBox "hello"
Run Code Online (Sandbox Code Playgroud)

我收到编译器错误

<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"
Run Code Online (Sandbox Code Playgroud)

有没有办法让这项工作?

Car*_*arl 19

你向编译器承诺,你放入的值ShowBox将具有该类型forall a. Show a => a.这种类型只有一个可能的值,而且它是_|_.我想你可能想要一个存在类型,看起来很相似,但意味着一些非常不同的东西.

{-# LANGUAGE ExistentialQuantification #-}

data ShowBox = forall a. Show a => ShowBox a
Run Code Online (Sandbox Code Playgroud)

这必须用data,而不是newtype.在这种情况下,构造函数上的模式匹配是将Show实例放入范围的原因.由于newtypes没有运行时表示,因此它们无法存储存在量化所暗示的多态见证.

  • 也就是说:@ user1279710的`ShowBox`中的值必须能够是*Show*的任何*实例,但他试图将一个*特定的*Show`实例放入.(暂停主题更改)类型`forall a的唯一值.在这种情况下显示a => a`是`_ | _`,因为`Show`类型类不包含用于构造实例类型值的任何方法,仅用于消耗它们. (3认同)
  • 如果编译器发出"无用的数据声明:`Show a => a`:只能由`_ | _`居住"这样的警告会很好 (3认同)
  • 请记住,这个"ShowBox"与"String"相同.在许多情况下,存在类型可以简化为更简单的具体类型; 寻找这些机会,他们可以简化您的代码库. (3认同)

Lui*_*las 7

好吧,你的Show构造函数有这种类型:

Show :: (forall a. Show a => a) -> ShowBox
Run Code Online (Sandbox Code Playgroud)

你试图将这个函数应用于[Char]不是类型的类型forall a. Show a => a,因为它a是一个"Skolem变量",只能在非常严格的规则下与其他类型统一(其他人能够比我更好地解释).

你确定以下不是你想要的(modulo datavs. newtype)吗?为什么要forall在构造函数内部进行范围调整?

-- Show :: Show a => a -> ShowBox
data ShowBox = forall a. Show a => Show a
Run Code Online (Sandbox Code Playgroud)