假设我想编写一个处理播客订阅的应用程序。为了存储来自该订阅的解析信息,我会编写类似以下内容的代码:
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中定义这些关系仍然是主要问题)。