后台:我正在使用Haskell中的第一个完整程序,这是一个在命令行上的简单待办事项列表应用程序。
我的问题是结构之一,有两个层次:(1)最好的方法是什么? (2)什么是Haskell(功能)方法呢?我这样说的原因是因为我怀疑可能有一种更快或更简单的方法来忽略函数式编程的原理。我想以更优雅和清晰的方式做到这一点,因为它更像是一种学习练习而不是其他任何东西。
请记住,我(显然)希望应用程序有点持久。表格中的两个选项现在是将信息存储在平面文本文件中,或者交替存储在Sqlite数据库中。
首先想到的结构是这样的,其中ToDoList类型对象只是ToDo项目的列表:
import Data.List
import Data.Time
data ToDo = ToDo {
todoId :: Int,
todoDue :: ZonedTime,
todoCreated :: UTCTime,
todoItem :: String,
todoPriority :: Priority,
todoStatus :: Status
}
deriving (Show, Read)
type ToDoList = [ToDo]
data Priority = Low | Medium | High
deriving (Show, Read, Eq, Ord)
data Status = Complete | InProgress | Open
deriving (Show, Read, Eq, Ord)
但后来我开始想知道如何最好地存储这种类型的物体。这是否意味着我将它们存储在一个平面文件中?有没有办法将像这样的高度指定类型的对象与数据库中的字段/列相关联?
当我考虑使用Sqlite数据库时,似乎所有的工作都将在数据库调用中完成,而Haskell类型与它相比几乎没有。这看起来很糟糕。
总之,问题是我如何最好地模拟我的简单待办事项列表应用程序的数据结构,以符合函数式编程和Haskell理想的概念,我正在寻求实践项目
答案 0 :(得分:7)
Show / Read组合是一种非常简单的序列化和反序列化应用程序内部状态的方法,并且由于纯度,它基本上总是有效。此外,您可以很好地编写切片和骰子列表的函数,因为您将能够将列表视为完全加载到内存中(并且如果您想要使用更高效的数据结构,那么您可以查看优化不同查询的方法。)
例如,如果我想在某个日期之前找到所有到期的项目,我可以使用过滤器来写这个:
dueBefore (ToDoList ts) d = ToDoList (filter (\t -> due t <= d) ts)
你的伪代码上的一些样式挑剔:
由于所有访问器函数(id,die。created ...)都被转储到模块范围的命名空间中,因此使用记录名称(例如todoId,todoDie)为它们添加前缀/后缀是一种很好的方式。在这种特殊情况下,id
是一个真正的函数,所以你不应该遮蔽它!
ToDoList是一个带有一个值的构造函数数据类型;你可能实际上只是想要一个newtype或类型同义词。 (练习:重写上面的代码片段以使用类型同义词。)
您可能需要优先级和状态<{p>
Ord
个实例
答案 1 :(得分:2)
我认为平面文件会让你的生活变得更轻松,并且也能正常工作,除非你有如此可怕的积压工作,你需要一个数据库才能完成所有工作; P
我会建议阅读Learn You a Haskell for Great Good,或者至少是chapter。它甚至包含一个类似于你要写的短TODO应用程序。
现在,应该在写入和读取文件的所有值时没有问题,只要它们都得到显示和读取。