Ответ 1
Нет, согласно 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
например.
*Main> main
"foo"
7
'x'
Логически, вам нужен словарь (или тег), выделенный где-то. И это не имеет смысла, если вы удалите конструктор.
Примечание. Вы не можете использовать функции unbox, хотя, как вы, кажется, намекаете, или полиморфные поля.
Есть ли способ (возможно, просто использовать
-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
открыт.