解决haskell数据记录中的循环依赖性

时间:2014-03-27 18:42:49

标签: haskell record cyclic-dependency

想象一下,我想编写一个处理播客源的应用程序。为了存储来自这样一个feed的解析信息,我会写这样的东西:

data Podcast = Podcast {
    podcastTitle :: String, -- ^ title of podcast
    episodes :: [Episode]   -- ^ list of episodes of podcast
    ...                     -- ^ some other fields
} deriving (Show)

data Episode = Episode {
    episodeTitle :: String, -- ^ title of episode
    podcast :: Podcast      -- ^ podcast this episode belongs to
    ...                     -- ^ some other fields
} deriving (Show)

以上数据记录定义反映了数据类型之间常见的1:n关系:播客有很多集,而剧集属于一个播客。现在我在定义这样的播客时遇到问题:定义Podcast我已经需要剧集列表但是要定义Episode实体我需要Podcast实体。在我看来,在haskell中解决这种循环依赖是不可能的......

我也认为上面的代码是我在其他语言编程时的遗留问题。在上面的样式中,我会在python中做到这一点,但是这种编程语言有一个状态概念。在python中,我可以先定义一个没有剧集的Podcast实体,然后用定义的Podcast实体初始化所有剧集,然后将播客的episodes字段设置为剧集列表。

我的问题:播客和剧集之间的1:n关系建模的haskell方式是什么?

评论中的问题解答:

为什么剧集必须引用特定的播客?拥有一个功能会很好

podcast :: Episode -> Podcast

在我需要的时候返回剧集的播客。我知道,一个解决方案是将Podcast实体传递给剧集的每个函数,即我替换每个函数

func1 :: Episode -> Something

我需要上面的podcast函数

func1 :: Podcast -> Episode -> Something

编写尽可能少的代码并且不必在任何地方携带Podcast实体,这将是一件好事。

也许我稍微改变了我的问题:在没有Episode字段的情况下定义podcast数据记录是完全可以的。如何实施

podcast :: Episode -> Podcast

在这种情况下?

如果有人稍后制作播客,其中包括来自其他播客的剧集怎么办?在我的情况下,这不会发生,即使是这样,也可以考虑同一集作为不同的。 (事实上​​,考虑到这个问题会将1:n关系提升为n:n关系,但是如何在haskell中定义这些关系的主要问题仍然是相同的。)

1 个答案:

答案 0 :(得分:4)

在Haskell中,循环依赖实际上非常简单。在let语句中,任何绑定的定义都可以引用任何其他绑定。

let pc = Podcast "the name" [ep1, ep2]
    ep1 = Episode "first" pc
    ep2 = Episode "second" pc

懒惰会照顾你。

作为一般规则,DBMS是此类信息的最佳选择。