我希望能够做这样的事情,这显然是不允许的。
import qualified Data.Map as Map
x = Map.fromList [
("Name", ["John", "Steve", "Kelly", "Zoe"]),
("Surname", ["Smith", "Lee", "Ng", "White"]),
("Age", [1, 2, 3, 4])
]
Run Code Online (Sandbox Code Playgroud)
一种可能的解决方案是创建这样的类型:
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])
]
Run Code Online (Sandbox Code Playgroud)
这是不可取的。有没有更好的方法?
我的实际用例:非常广泛,我正在尝试实现 dplyr ( http://cran.r-project.org/web/packages/dplyr/vignettes/introduction.html ) 的一部分,可以将其视为“语法数据的”。Dplyr 具有用于表格数据的列和行选择以及行的分组和连接的表达式,其中行数可以是数百万,列数可以是数百。我现在关心的不是数据大小,而是生成与该包类似的功能和工作流程的能力
您可以为此使用存在量化
{-# 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])
]
Run Code Online (Sandbox Code Playgroud)
(请注意,在最后一列中,我们需要显式类型注释,因为文字已重载,而存在主义无法完全应对这一点)。
当然,现在无法从 中获得映射数据的真实类型x。你只有forall a . a => Column a,而且你唯一能用它做的就是调用 的方法class Column。本示例未定义任何内容。您应该添加自己的方法,并且必须明智地选择。
请注意,由于我不太明白的原因,许多铁杆 Haskellers 都不赞成这种技术。如果有人能阐明这一点,那就太好了。