想象一下,我想编写一个处理播客提要的应用程序。要存储来自此类提要的解析信息,我会编写如下内容:
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 中定义这些关系的主要问题仍然是相同的)。