如果我想声明newtype
使得值的类型类型被约束为具有类型类的实例,那么我似乎可以这样做:
{-# 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"
有没有办法让这项工作?
答案 0 :(得分:19)
您向编译器承诺,您放在ShowBox
中的值将具有forall a. Show a => a
类型。该类型只有一个可能的值,它是_|_
。我想你可能想要一个存在主义类型,看起来很相似,但意味着一些非常不同的东西。
{-# LANGUAGE ExistentialQuantification #-}
data ShowBox = forall a. Show a => ShowBox a
必须使用data
,而不是newtype
。在这种情况下,构造函数上的模式匹配是将Show实例放入范围的原因。由于newtype
没有运行时表示,因此它们无法存储存在量化所暗示的多态见证。
答案 1 :(得分:7)
好吧,您的Show
构造函数具有以下类型:
Show :: (forall a. Show a => a) -> ShowBox
您尝试将此函数应用于[Char]
类型forall a. Show a => a
,因为a
是“Skolem变量”,只能与其他类型统一在非常严格的规则下(其他人将能够比我更好地解释)。
您确定以下内容不是您想要的(模data
与newtype
模数)吗?为什么要将forall
放在构造函数中?
-- Show :: Show a => a -> ShowBox
data ShowBox = forall a. Show a => Show a