解决Haskell数据记录中的循环依赖问题

4

假设我想编写一个处理播客订阅的应用程序。为了存储来自该订阅的解析信息,我会编写类似以下内容的代码:

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)

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

我还认为上面的代码是我在其他语言编程的古董。在上述的风格中,例如在Python中,我可以首先定义一个不带剧集的Podcast实体,然后用定义的Podcast实体初始化所有的剧集,并将播客的episodes字段设置为剧集列表。

我的问题:如何用Haskell建模播客和剧集之间的一对多关系?

评论中的问题答案:

为什么必须让一集引用一个特定的播客?拥有一个函数很好。

podcast :: Episode -> Podcast

每当我需要它时,它会返回该剧集的播客。我知道,一个解决方案是为每个剧集的函数也传递Podcast实体,即我替换每个函数。

func1 :: Episode -> Something

我需要以上所述的 播客 功能。

func1 :: Podcast -> Episode -> Something

尽可能少地编写代码,而不必到处携带Podcast实体,这将非常有好处。

也许我可以稍微改变一下我的问题:完全可以定义没有podcast字段的Episode数据记录。如何实现?

podcast :: Episode -> Podcast

在这种情况下呢?

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


一个集必须引用特定的播客,为什么?如果稍后有人制作了一个包含其他播客集的播客该怎么办? - JAB
@JAB:我修改了我的问题并回答了你的问题... - Stephan Kulla
1个回答

4

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

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

您不必操心,这将由“懒惰”机制代劳。

总的来说,DBMS是处理此类信息的最佳选择。


谢谢您的快速回答!什么是DBMS? - Stephan Kulla

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接