简体   繁体   English

Haskell 中的代数数据类型

[英]Algebraic Data Types in Haskell

Hello I have only worked with imperative programming so far and I am learning Haskell :)你好,到目前为止我只使用过命令式编程,我正在学习 Haskell :)

I have the following algebraic data types:我有以下代数数据类型:

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)

and I need to do some calculations with those.我需要用这些做一些计算。 My first thought was mapping the Days and Months to Ints and do the calculations from there.我的第一个想法是将天数和月数映射到整数并从那里进行计算。 For example:例如:

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

My question is:我的问题是:

  1. Is this a good solution for my problem?这是解决我的问题的好方法吗?
  2. How could i convert the Days/Months into Ints in a function given I have those maps.鉴于我有这些地图,我如何在函数中将天/月转换为整数。

Thanks in advance!提前致谢! :) :)

Don't, and I repeat don't do date and time calculations yourself.不要,我再说一遍不要自己计算日期和时间。 Ship out to a good library .运送到一个好的图书馆 See also Falsehoods programmers believe about time for an incomplete list of reasons to do this.另请参阅程序员认为时间错误的不完整原因列表。

Answering your questions:回答您的问题:

There are many ways of doing what you are looking for, and a practical way would be to use a library, as already pointed out.有很多方法可以做你正在寻找的东西,正如已经指出的那样,一种实用的方法是使用图书馆。 Even better, find a library and read the source code.更好的是,找到一个库并阅读源代码。 Hoogle is your friend. Hoogle是你的朋友。


But For learning Haskell purposes:但是为了学习 Haskell 的目的:

Instead of mapping them manually you could try provide a function.您可以尝试提供一个函数,而不是手动映射它们。 And because this is a behaviour you want more types to share you could create a Type Class.并且因为这是您希望更多类型共享的行为,您可以创建一个类型类。 One naive (maybe didactic, less so practical, maybe fun to play with) way would be:一种天真的(可能是说教,不太实用,可能玩起来很有趣)的方式是:

  1. Define a Class that provides a way to convert to and from Int, let's call it ToInt .定义一个提供与 Int 相互转换的方法的类,我们称之为ToInt Now you have a common interface of getting that behaviour out of all your Types现在你有一个通用的接口来从你的所有类型中获取这种行为
class ToInt a where
  toInt   :: a -> Int
  fromInt :: Int -> Maybe a

Now you can implement your to and from for your types and use them to convert.现在您可以为您的类型实现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 = ...

Note that this is a simple but bad example.请注意,这是一个简单但糟糕的示例。

You can see the tedious nature of both implementation, and the limited help you get from the type checker.您可以看到这两种实现的乏味本质,以及您从类型检查器中获得的有限帮助。 But once you start implementing something, you get a feel for what works and what not.但是,一旦您开始实施某事,您就会了解哪些有效,哪些无效。 Then you can search for how others deal with these issues in the actual libraries, for example .然后你可以在实际库中搜索其他人如何处理这些问题, 例如

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM