【发布时间】:2012-10-27 06:35:54
【问题描述】:
我正在尝试构建异构索引结构并提出以下解决方案,但 I was told not to use existential types.
你能找到更好的解决方案吗?
我想保持接口定义(type 和class)和具体实现(data 和instance)之间的分离。 编辑遵循@hammar的评论:在实际应用中,值不是Shown,而是简单地存储一个查询;还 myData 是更复杂的附加记录。
如果这可以带来更好的解决方案,那么确切的要求是构建地图地图(内部地图)。每个内部映射都是同质的,形式为Map String a,但是每个内部映射可能对其值强制使用不同的类型。您也可以将其视为两级索引结构。实现不必使用Data.Map,但必须高效。
{-# LANGUAGE ExistentialQuantification #-}
module Scratch.SO_ExtistentialTypes where
import Data.Map
data HeteroValue = forall a. Show a => HV a
instance Show HeteroValue where
show (HV b) = show b
type MyMap = Map String HeteroValue
class MyClass c where
getMyMap :: c -> MyMap
data MyData = MyData {
myMap :: MyMap
}
instance MyClass MyData where
getMyMap = myMap
这个 sn-p 可以使用 ghci 运行
let myMap = fromList [("key1", HV "abc"), ("key2", HV 123)] :: MyMap
let myData = MyData myMap
getMyMap myData
【问题讨论】:
-
@hammar
Show只是为了在ghci中测试这个 sn-p。在实际应用中,这些值是不显示的,只是存储和查询。 -
真正的问题不是您是否应该使用存在类型或其他此类功能,而是您是否应该尝试存储这样的异构值。为什么你需要它们是异质的?你真正想在这个索引结构中存储什么?静态类型是你的朋友。静态类型将您从痛苦的世界中拯救出来。动态类型不是一个很酷的语言功能,它是一个 hack。你可以放任何你喜欢的东西,但另一方面,在运行时世界可以给你任何它喜欢的东西。
-
@AndrewC 这是一种意见。我的理解是当你写'forall a.合同 a =>` 你对“世界”的所有要求是他们“给你”的东西尊重“合同”。这完美地反映了我的意图。也许我的世界观更“动态”? :)
-
是的,意见。如果你真的是这个意思,你可以这样 - 看我的回答。除了您想以 OO 样式对其进行编码之外,您还没有阐明程序的目的。你想存储什么?存储后你想用它做什么?