我希望能够做到这样的事情,这显然是不允许的。
import qualified Data.Map as Map
x = Map.fromList [
("Name", ["John", "Steve", "Kelly", "Zoe"]),
("Surname", ["Smith", "Lee", "Ng", "White"]),
("Age", [1, 2, 3, 4])
]
一种可能的解决方案是创建一个这样的类型:
data L = LInt [Int] | LString [String]
x = Map.fromList [
("Name", LString ["John", "Steve", "Kelly", "Zoe"]),
("Surname", LString ["Smith", "Lee", "Ng", "White"]),
("Age", LInt [1, 2, 3, 4])
]
这是不受欢迎的。有更好的方法吗?
我的实际使用案例: 非常广泛地说,我正在尝试实现dplyr(http://cran.r-project.org/web/packages/dplyr/vignettes/introduction.html)的部分,这可以被视为数据的语法"。 Dplyr具有表格数据的列和行选择以及行的分组和连接的表达式,其中行数可以是数百万,列数是数百。它不是我现在关注的数据大小,而是能够生成与该软件包类似的功能和工作流程
答案 0 :(得分:3)
您可以使用存在量化
{-# LANGUAGE ExistentialQuantification, FlexibleInstances, TypeSynonymInstances #-}
import qualified Data.Map as Map
class ColumnData c
instance ColumnData Integer
instance ColumnData String
data Column = forall c . ColumnData c => Column [c]
x = Map.fromList [
("Name", Column ["John", "Steve", "Kelly", "Zoe"]),
("Surname", Column ["Smith", "Lee", "Ng", "White"]),
("Age", Column [1::Integer, 2, 3, 4])
]
(注意我们在最后一列中需要一个显式的类型注释,因为文字被重载,而存在不能完全解决这个问题。)
当然,x
无法获得映射数据的真实类型。您只有forall a . a => Column a
,而您唯一能做的就是调用class Column
的方法。此示例定义none。你应该添加自己的方法,你必须明智地选择。
请注意,这项技术不受许多铁杆打击者的欢迎,原因我不太了解。如果有人能够对此有所了解,那就太好了。