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

时间:2019-07-11 12:42:56

标签: haskell polymorphism gadt

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

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

现在,我想使用(并保存)对列表元素的某种引用(例如,使用指向其在列表中位置的索引-现在让我们想象一下列表没有更改,因此这是一个好主意)。我希望能够引用那些我不在乎“排序”的元素,但要注意的是:我希望能够引用元素并以类型告诉它它来自某些具体排序。这排除了上面的简单求和类型解决方案(因为排序不在类型中!)。我尝试使用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"

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

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

我该如何解决?我不是要寻求针对此特定错误的解决方案(我想这是一个死胡同吗?),或者不是专门针对GADT甚至是使用int索引进行引用等等,我只是想要一种解决方案,

  • 解决了间接引用一些非特定对象和某些特定对象的基本问题
  • 不使用STRef或类似工具,因此我的整个程序都必须是monad(因为这是一个非常中心的数据结构)

1 个答案:

答案 0 :(得分:4)

“暗示多态性”表示您有一个∀,它包装在->以外的类型构造函数中。在这种情况下,请输入[]。正如错误消息所告诉您的那样,GHC Haskell不支持此操作(不是从原则上讲不明智,但据我所知,它使类型检查成为噩梦)。

这可以通过将wrapping包裹在一个形成“类型检查器障碍”的东西中来解决:

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

实际上,这可以简化,因为ElementRef本身只是带有幻像类型参数的新型包装器:

newtype UnspecificElementRef = UnspecificElementRef Int