(GHC)Haskell是否有可能定义一个存在量化的新类型?我理解如果涉及类型类,则无法在字典传递实现中完成,但对于我的目的,不需要类型类。我真正想要定义的是:
newtype Key t where Key :: t a -> Key t
但GHC似乎并不喜欢它。目前我正在使用data Key t where Key :: !(t a) -> Key t
。有没有办法(可能只是使用-funbox-strict-fields
?)来定义一个与上面的newtype版本具有相同语义和开销的类型?我的理解是,即使有严格的字段取消装箱,仍然会有一个额外的标签字,但我可能完全错了。
这不是导致我出现明显性能问题的原因。让我感到惊讶的是,不允许使用newtype。我是一个天生好奇的人,所以我不禁想知道我的版本是否被编译为相同的表示形式,或者是否可以定义任何等效类型。
答案 0 :(得分:6)
不,GHC表示:
newtype构造函数不能具有存在上下文
然而,data
很好:
{-# LANGUAGE ExistentialQuantification #-}
data E = forall a. Show a => E a
test = [ E "foo"
, E (7 :: Int)
, E 'x'
]
main = mapM_ (\(E e) -> print e) test
E.g。
*Main> main
"foo"
7
'x'
逻辑上,你做需要在某处分配的字典(或标签)。如果你删除了构造函数,这没有意义。
注意:你不能像现在所暗示的那样打开函数,也不能打开多态字段。
有没有办法(可能只是使用
-funbox-strict-fields
?)来定义一个与上面的newtype版本具有相同语义和开销的类型?
删除-XGADT有助于我思考:
{-# LANGUAGE ExistentialQuantification #-}
data Key t = forall a. Key !(t a)
如同,Key (Just 'x') :: Key Maybe
所以你想保证Key
构造函数被删除。
以下是GHC中用于检查newtype
上的约束类型的代码:
-- Checks for the data constructor of a newtype
checkNewDataCon con
= do { checkTc (isSingleton arg_tys) (newtypeFieldErr con (length arg_tys))
-- One argument
; checkTc (null eq_spec) (newtypePredError con)
-- Return type is (T a b c)
; checkTc (null ex_tvs && null eq_theta && null dict_theta) (newtypeExError con)
-- No existentials
; checkTc (not (any isBanged (dataConStrictMarks con)))
(newtypeStrictError con)
-- No strictness
我们可以看到为什么!
对表示没有任何影响,因为它包含多态组件,因此需要使用通用表示。并且未提升的newtype
没有意义,也不是非单身的构造函数。
我唯一能想到的是,就像存在的记录访问器一样,如果newtype
被暴露,则opaque类型变量将被转义。
答案 1 :(得分:3)
我认为没有任何理由不能使其工作,但也许ghc有一些内部代表问题。