代数数据类型的特定用例

时间:2011-11-21 19:22:28

标签: haskell

我正在编写一个通用的枚举器来抓取网站作为练习,我做了它,它完整且工作正常,但我有一个问题。您可以在此处找到它:https://github.com/mindreader/scrape-enumerator如果您想查看代码。

基本的想法是我想要一个枚举器,它会在搜索引擎,博客,你必须获取页面的内容等页面上吐出站点定义的条目,并且它将有25个条目,并且你希望一次只输入一个条目。但与此同时,我不想为每个站点编写管道,所以我想要一个通用接口。我想出的是(这使用类型系列):

class SiteEnum a where
  type Result a :: *
  urlSource :: a -> InputUrls (Int,Int)
  enumResults :: a -> L.ByteString -> Maybe [Result a]

data InputUrls state =
  UrlSet [URL] |
  UrlFunc state (state -> (state,URL)) |
  UrlPageDependent URL (L.ByteString -> Maybe URL)

为了在每种类型的网站上执行此操作,这需要某种类型的网址源,可能是预生成网址的列表(可能是无限的),或者它可能是初始状态以及从中生成网址的内容(如果网址包含& page = 1,& page = 2等),然后对于谷歌等真正搞砸的页面,给出一个初始网址,然后提供一个功能,搜索正文以查找下一个链接然后使用它。您的站点使数据类型成为SiteEnum的实例,并为Result提供类型,该类型取决于站点,现在枚举器处理所有I / O,您不必考虑它。这非常有效,我用它实现了一个站点。

我的问题是,这个实现有一个烦恼是InputUrls数据类型。当我使用UrlFunc时,一切都是金色的。当我使用UrlSet或UrlPageDependent时,它并不是所有有趣的游戏,因为状态类型是未定义的,我必须将其强制转换为:: InputUrls()才能进行编译。这似乎是完全没必要的,因为该类型变量由于编写程序的方式,将永远不会用于大多数站点,但我不知道如何解决它。我发现我想在很多不同的上下文中使用这样的类型,并且我总是最终得到只在数据类型的某些部分中需要的杂散类型变量,但它不觉得我应该使用就是这样。有没有更好的方法呢?

1 个答案:

答案 0 :(得分:2)

为什么你需要UrlFunc案件呢?根据我的理解,你使用状态函数做的唯一事情是使用它来构建像UrlSet中的那个列表,所以不是存储状态函数,而是存储结果列表。这样,您可以从数据类型中删除state类型变量,这样可以消除模糊问题。