以 Haskell 数据类型表示国家 ID 和文本
Posted
技术标签:
【中文标题】以 Haskell 数据类型表示国家 ID 和文本【英文标题】:Representing Country Id and Text in Haskell datatype 【发布时间】:2018-06-30 08:32:02 【问题描述】:我在 json 中有一个国家/地区 ID 和国家/地区文本列表
1 : "country one",
2 : "country two"
我已经创建了下面的代码来表示 haskell 中的国家 ID 和文本
data Country a = Country a
country1 :: Country String -- Representing country name
country1 = Country "country one"
country2 :: Country Integer -- Representing country id
country2 = Country 2
以上代码运行良好。但我想限制 a 只取字符串和整数的值。
为此,我尝试了以下代码。但是,它不起作用。
-# LANGUAGE GADTs #-
data Country a where
Country :: (String, Integer) => a -> Country a
toId :: Country String -> Country Integer
toId Country a = Country 1
toText :: Country Integer -> Country String
toText Country a = Country "country one"
任何人都可以帮助弄清楚我如何以最佳方式实现上述代码以使其正常工作吗?
【问题讨论】:
这种表示方式很奇怪。我希望一个国家同时带有它的 id 和 name,所以Country Int String
作为构造函数。详尽地枚举a
的可能类型也是一种反模式,因为它会阻止代码重用。
实际上在 json 帖子中,我会收到国家名称,并将其转换为国家 ID,同时保存在数据库中。发布数据将类似于 "country" : "country one" 。因此,我试图分别代表国家名称和 id。
您说,“我想将a
的约束设置为仅采用String
和Integer
的值”。为什么要这个约束?
因为在我的用例中只有这两种类型是有效的。由于 a 是多态的,因此任何人都可以编写 Country SomeOtherType 这对于 Country 是无效的类型。我希望这是有道理的。
【参考方案1】:
国际海事组织,GADT 对这项任务来说太过分了。
你不能只使用 ADT 吗?
data Country = CountryWithInt Int
| CountryWithString String
【讨论】:
我同意 GADT 有点矫枉过正,但这种表示形式似乎比data Country a = Country a
更糟糕:不能写出Country Int -> Country String
类型,反之亦然,以保证给定的国家标识符在适当的格式输入和输出。
这是更好的表示吗? newtype CountryId = CountryId Int
和 newtype CountryText = CountryText String
还是我应该研究一下 GADT?
是的,如果你想编写像Country Int -> Country String
这样的函数,这绝对是更好的表示。请注意,您的类型在它们之间不共享任何内容,因此将它们包装成单一类型是错误的想法。以上是关于以 Haskell 数据类型表示国家 ID 和文本的主要内容,如果未能解决你的问题,请参考以下文章
将抽象数据类型保存和加载到 json 文件并从游戏中的文件中读取 Haskell