【问题标题】:Algebraic Data Types in HaskellHaskell 中的代数数据类型
【发布时间】:2021-10-28 02:49:51
【问题描述】:

您好,到目前为止,我只使用过命令式编程,并且正在学习 Haskell :)

我有以下代数数据类型:

data Day   = I | ... | XXXI deriving(Ord,Eq)    (Days in roman numerals)
data Month = Jan | ... | Dec deriving(Ord,Eq)   (Months abbreviated to 3 letters)
data Year  = 0 | ... | 2021                     (actually Ints)

我需要对这些进行一些计算。我的第一个想法是将日期和月份映射到整数并从那里进行计算。例如:

dayConversionMap   = [(I,1), (II,2), (III,3), (IV,4), ... , (XXXI,31)]
monthConversionMap = [(Jan,1), (Feb,2), (Mar,3), ... , (Dec,12)]

我的问题是:

  1. 这是解决我的问题的好方法吗?
  2. 如果我有这些地图,我如何在函数中将天/月转换为整数。

提前致谢! :)

【问题讨论】:

  • 您能否说明您希望进行哪些计算?例如,如果您希望能够将一个月“加 1”(例如,从一月到二月),您可以推导出 Enum(假设您按顺序排列月份,因为它定义了基于此的枚举) 并使用succ。但这可能很脆弱,因为 IIRC 对 Dec 的“加 1”是派生的Enum 的错误。如果您想将日期作为一个整体使用,则应该有日期时间库。等等。
  • 我想计算从日期 1.1.0000 到 X.X.XXXX(基本上任何日期)所经过的分钟数
  • 请注意,虽然如果您只想涵盖最常见的情况,这可能是一个很好的学习练习,但要找到正确的日期非常困难,而且有很多例外。例如,因为没有年份 0000,所以没有日期 1.1.0000:我们从公元前 1 年到公元 1 年,中间没有“0 年”。闰年、闰秒、儒略到格里高利转换等。一场噩梦。

标签: haskell algebraic-data-types


【解决方案1】:

不要,我再说一遍不要自己计算日期和时间。发货至a good library。另请参阅 Falsehoods programmers believe about time 了解不完整的原因列表。

【讨论】:

  • 感谢您在处理时间时提供的教育性陷阱清单,并指出自己处理时间可能不是一个好主意;)一定要记住这一点!尽管在这种情况下它纯粹是为了学习haskell的工具:)
【解决方案2】:

回答您的问题:

有很多方法可以做你正在寻找的事情,正如已经指出的那样,一种实用的方法是使用库。更好的是,找到一个库并阅读源代码。 Hoogle 是你的朋友。


但是为了学习 Haskell 的目的:

您可以尝试提供一个函数,而不是手动映射它们。并且因为这是您希望更多类型共享的行为,您可以创建一个类型类。一种天真的(可能是说教,不太实用,可能玩起来很有趣)的方式是:

  1. 定义一个提供与 Int 相互转换的方法的类,我们称之为ToInt。现在您有了一个通用接口,可以从所有类型中获取该行为
class ToInt a where
  toInt   :: a -> Int
  fromInt :: Int -> Maybe a

现在您可以为您的类型实现 tofrom 并使用它们进行转换。

instance ToInt Day where
  toInt x =  
    case x of
      I -> 1
      II -> 2 
--    ...

  fromInt x = 
    case x of 
      1 -> I
--    ...

instance ToInt Month where 
-- ...
calculation :: Day -> Month -> Year -> Int
calculation d m y = doSomething (toInt d) 
  where 
    doSomething :: Int -> Int 
    doSomething = ...

请注意,这是一个简单但不好的示例。

您可以看到这两种实现的繁琐本质,以及您从类型检查器获得的有限帮助。但是,一旦您开始实施某些东西,您就会对哪些有效,哪些无效。然后你可以在实际库中搜索其他人是如何处理这些问题的,for example

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多