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