Подтвердить что ты не робот

Есть ли способ определить экзистенциально квантифицированный новый тип в GHC Haskell?

Возможно ли в (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 выше? Мое понимание заключается в том, что даже при строгом поле unboxed все равно будет добавлено дополнительное слово, хотя я мог бы быть совершенно не там.

Это не то, что вызывает у меня заметные проблемы с производительностью. Меня просто удивило, что новый тип не допускается. Я, естественно, любопытный человек, поэтому я не могу не задаться вопросом, скомпилирована ли версия, которую я имею, с тем же представлением или может быть определен какой-либо эквивалентный тип, который будет.

4b9b3361

Ответ 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

enter image description here

Итак, вы хотите гарантировать, что конструктор 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 открыт.

Ответ 2

Я не вижу причин, по которым это невозможно заставить работать, но, возможно, у ghc есть проблемы с внутренним представлением.