间接引用Haskell中不带单子的特定和非特定对象

间接引用Haskell中不带单子的特定和非特定对象,haskell,polymorphism,gadt,Haskell,Polymorphism,Gadt,我想在容器数据结构(列表、集合等)中存储一组不同“排序”的元素,并从其他地方间接引用它们。通常情况下,您可能会对元素使用sum类型,也可能使用列表作为容器或类似对象: data Element = Sort1 | Sort2 String | ... type ElementList = List Element 现在,我想使用(并保存)一些对列表元素的引用(例如,使用一个索引到它在列表中的位置-让我们现在想象一下,列表没有改变,因此这是一个好主意)。我希望能够在不关心“排序”的情况下引用元素

我想在容器数据结构(列表、集合等)中存储一组不同“排序”的元素,并从其他地方间接引用它们。通常情况下,您可能会对元素使用sum类型,也可能使用列表作为容器或类似对象:

data Element = Sort1 | Sort2 String | ...
type ElementList = List Element
现在,我想使用(并保存)一些对列表元素的引用(例如,使用一个索引到它在列表中的位置-让我们现在想象一下,列表没有改变,因此这是一个好主意)。我希望能够在不关心“排序”的情况下引用元素,这里有一个问题:我还希望能够引用元素并在类型中指出它来自某个特定的排序。这排除了上面的简单求和类型解决方案(因为排序不在类型中!)。我尝试了一种GADTs解决方案:

{-#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索引进行引用等等,我只是想要一个解决方案:

  • 解决了间接引用非特定内容和特定内容的基本问题
  • 不使用STRef或类似工具,因此我的整个程序需要是一个monad(因为这是一个非常核心的数据结构)

    • “非指示多态性”表示您有∀ 它包装在类型构造函数中,而不是
      ->
      。在本例中,在
      []
      中。正如错误消息告诉您的那样,GHC Haskell不支持这一点(并不是说它在原则上不合理,但据我所知,它使类型检查成为一场噩梦)

      但这可以通过包装∀ 在形成“类型检查器屏障”的东西中:在新类型中

      newtype UnspecificElementRef = UnspecificElementRef (∀ t. ElementRef (Element t))
      type UnspecificElementRefs = [UnspecificElementRef]
      
      事实上,这可以简化,因为
      ElementRef
      本身只是一个带有幻影类型参数的新类型包装器:

      newtype UnspecificElementRef = UnspecificElementRef Int
      

      好的,这解决了引用非特定元素的问题,但是如何定义ElementList呢?我试过使用
      newtypelistelement=ListElement(对于所有t.Element t)
      typeelementslist=[ListElement]
      ,但这并不能编译。啊,你需要一个存在式,而不是通用式<代码>数据ListElement,其中ListElement::Element t->ListElement。