想象一下,我想编写一个处理播客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中定义这些关系的主要问题仍然相同)。

最佳答案

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

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


懒惰会为您解决这个问题。

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

10-01 17:16