在没有 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 索引进行引用等等,我只是想要一个解决方案:
- 解决了间接引用非特定事物和特定事物的基本问题
- 不使用 STRef 或类似的东西,所以我的整个程序需要是一个 monad(因为这是一个非常核心的数据结构)
“Impredicative polymorphism”意味着你有一个 ∀ 包裹在 ->
以外的类型构造函数中。在这种情况下,在 []
中。正如错误消息告诉你的那样,GHC Haskell 不支持这个(这并不是说它原则上不明智,但据我所知,它使类型检查成为一场噩梦)。
这可以通过将 ∀ 包装在形成“类型检查屏障”的东西中来解决:在新类型中。
newtype UnspecificElementRef = UnspecificElementRef (∀ t. ElementRef (Element t))
type UnspecificElementRefs = [UnspecificElementRef]
事实上,这可以被简化,因为 ElementRef
本身只是一个带有虚类型参数的新类型包装器:
newtype UnspecificElementRef = UnspecificElementRef Int
我想在容器数据结构(列表、集合、..)中存储一堆不同 "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 索引进行引用等等,我只是想要一个解决方案:
- 解决了间接引用非特定事物和特定事物的基本问题
- 不使用 STRef 或类似的东西,所以我的整个程序需要是一个 monad(因为这是一个非常核心的数据结构)
“Impredicative polymorphism”意味着你有一个 ∀ 包裹在 ->
以外的类型构造函数中。在这种情况下,在 []
中。正如错误消息告诉你的那样,GHC Haskell 不支持这个(这并不是说它原则上不明智,但据我所知,它使类型检查成为一场噩梦)。
这可以通过将 ∀ 包装在形成“类型检查屏障”的东西中来解决:在新类型中。
newtype UnspecificElementRef = UnspecificElementRef (∀ t. ElementRef (Element t))
type UnspecificElementRefs = [UnspecificElementRef]
事实上,这可以被简化,因为 ElementRef
本身只是一个带有虚类型参数的新类型包装器:
newtype UnspecificElementRef = UnspecificElementRef Int