在没有 monad 的情况下间接引用 Haskell 中的特定和非特定对象

Indirectly reference specific AND unspecific objects in Haskell without monads

我想在容器数据结构(列表、集合、..)中存储一堆不同 "sorts" 的元素,并从其他地方间接引用它们。通常,您可能会为元素使用求和类型,并可能使用列表作为容器或类似的类型:

data Element = Sort1 | Sort2 String | ...
type ElementList = List Element

现在我想使用(并保存)对列表元素的某种引用(例如,使用索引指向它在列表中的位置 - 让我们现在假设列表没有改变,这是因此是个好主意)。我希望能够在我不关心 "sort" 的地方引用元素,这里是要点:我 希望能够引用元素并在输入它来自某种特定的类型。这就排除了上面简单求和类型的解决方案(因为排序不在类型中!)。我尝试了 GADT 的解决方案:

{-#LANGUAGE GADTs, EmptyDataDecls, RankNTypes, ScopedTypeVariables #-}
data Sort1
data Sort2

data Element t where
  Sort1Element :: Element Sort1
  Sort2Element :: String -> Element Sort2

newtype ElementRef a = ElementRef Int

type UnspecificElementRefs = [forall t. ElementRef (Element t)]
type OneSpecificSort1ElementRef = ElementRef (Element Sort1)

main = do
  let unspecificElementRefs :: UnspecificElementRefs = [ElementRef 1, ElementRef 2]
  let oneSpecificElementRef :: OneSpecificSort1ElementRef = ElementRef 1
  putStrLn "hello"

但这给了我错误: - 非法多态类型:forall t。 ElementRef (Element t) - GHC 还不支持谓词多态性 - 在“UnspecificElementRefs”的类型同义词声明中

   |
11 | type UnspecificElementRefs = [forall t. ElementRef (Element t)]
   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

我该如何解决这个问题?我不是在寻找这个特定错误的解决方案(我想这是一个死胡同?)或者特别是 GADT 或者甚至使用 int 索引进行引用等等,我只是想要一个解决方案:

“Impredicative polymorphism”意味着你有一个 ∀ 包裹在 -> 以外的类型构造函数中。在这种情况下,在 [] 中。正如错误消息告诉你的那样,GHC Haskell 不支持这个(这并不是说它原则上不明智,但据我所知,它使类型检查成为一场噩梦)。

这可以通过将 ∀ 包装在形成“类型检查屏障”的东西中来解决:在新类型中。

newtype UnspecificElementRef = UnspecificElementRef (∀ t. ElementRef (Element t))
type UnspecificElementRefs = [UnspecificElementRef]

事实上,这可以被简化,因为 ElementRef 本身只是一个带有虚类型参数的新类型包装器:

newtype UnspecificElementRef = UnspecificElementRef Int