问题描述
我正在尝试构建异构索引结构,并提出了以下解决方案,但。
你能看到更好的解决方案吗?
>我想保持接口定义( type 和 class )和具体实现( data 和 instance )。 编辑后面的@ hammar的评论:在实际应用中,值不是 Show n,而只是存储查询;另外 myData 对于其他记录来说更为复杂。如果这可能导致更好的解决方案,那么确切的要求是建立地图(内部地图)的地图。每个内部映射都是同类的,并且以映射字符串a 的形式,但是每个内部映射可以为其值执行不同的类型。您也可以将其视为两级索引结构。这个实现不必使用 Data.Map ,但必须是有效的。
{ - #语言ExistentialQuantification# - }
模块Scratch.SO_ExtistentialTypes其中
进口Data.Map
数据HeteroValue = FORALL一个。显示a => HV a
实例显示HeteroValue其中
显示(HV b)=显示b
类型MyMap = Map String HeteroValue
class MyClass c其中
getMyMap :: c - > MyMap
MyData = MyData {
myMap :: MyMap
}
实例MyClass MyData其中
getMyMap = myMap
这段代码可以使用ghci运行
let myMap = fromList [(key1,HVabc),(key2,HV 123)] :: MyMap
let myData = MyData myMap $ b $ getMyMap myData
href =http://hackage.haskell.org/packages/archive/base/latest/doc/html/Data-Dynamic.html =nofollow> Data.Dynamic 。
模块Scratch.SO_Dyn其中
导入Data.Dynamic
导入Data.Map
type MyMap = Map String Dynamic
class MyClass c其中
getMyMap :: c - > MyMap
MyData = MyData {
myMap :: MyMap
}
实例MyClass MyData其中
getMyMap = myMap
您要放入此映射的数据必须派生Typeable。
使用 { - #LANGUAGE DeriveDataTypeable# - } 和派生(Data,Typeable),
另请参阅。
然后,您可以将数据转换为 Dynamic 键入 toDyn ,并安全地将它从动态类型转换为 fromDynamic 。
虽然这是一个非常有效的方法,但我和其他Haskellers会强烈建议您考虑制作自定义数据类型,而不是诉诸于真正异构的集合。假设(本着万圣节的精神),你知道一个事实,即你将要放入这张地图的唯一事物是 Cat s,女巫 es和 Ghoul s。
数据Cat = ...
data Witch = ...
data Ghoul = ...
通过简单标记每个可能的选项,您可以稍后确定每件事情。
数据HeteroValue
= DarkOmen Cat
|哈格女巫
| Haunting食尸鬼
案例(Map.lookup午夜访客的地图)
Just(DarkOmen猫) - >嘘猫
Just(Hag witch) - > cuckle witch
Just(萦绕食尸鬼) - > spook ghoul
Nothing - >错误...
I am trying to build an heterogeneous indexed structure and came up with the following solution but I was told not to use existential types.
Can you see a better solution ?
I would like to keep the separation between the definition of the interfaces (the type and class) and the concrete implementation (the dataand instance). Edit following @hammar's comment: in the real application, values are not Shown but simply stored an queried; also myDatais more complex with additional records.
If this can lead to a better solution, the exact requirement is to build a map of maps (the inner maps). Each inner map is homogeneous and in the form of Map String a however each inner map may enforce a different type for its values. You may also think of it as a two level indexed structure. The implementation does not have to use a Data.Map but must be efficient.
{-# 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
This snippet can be run using ghci
let myMap = fromList [("key1", HV "abc"), ("key2", HV 123)] :: MyMap let myData = MyData myMap getMyMap myData
One way to do "heterogeneous collections" is with Data.Dynamic.
module Scratch.SO_Dyn where import Data.Dynamic import Data.Map type MyMap = Map String Dynamic class MyClass c where getMyMap :: c -> MyMap data MyData = MyData { myMap :: MyMap } instance MyClass MyData where getMyMap = myMap
The data you wish to put into this map must derive Typeable.
Use {-# LANGUAGE DeriveDataTypeable #-} and deriving (Data, Typeable),see also http://www.haskell.org/ghc/docs/7.6.1/html/users_guide/deriving.html#deriving-typeable.
You can then cast your data to the Dynamic type with toDyn, and safely cast it from the Dynamic type with fromDynamic.
Although this is a perfectly valid approach, I and many other Haskellers would highly recommend that you consider making a custom data type rather than resorting to a truly heterogeneous collection. Suppose (in the spirit of Halloween) that you know for a fact that the only sorts of things you will put into this map are Cats, Witches, and Ghouls.
data Cat = ... data Witch = ... data Ghoul = ...
By simply tagging each possible option, you can later determine what each thing is.
data HeteroValue = DarkOmen Cat | Hag Witch | Haunting Ghoul case (Map.lookup "Midnight visitor" theMap) of Just (DarkOmen cat) -> hiss cat Just (Hag witch) -> cackle witch Just (Haunting ghoul) -> spook ghoul Nothing -> error ...
这篇关于没有存在类型的异构索引结构?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!