我正在编写一个通用的枚举器来抓取网站作为练习,我做了它,它是完整的并且工作正常,但我有一个问题.你可以在这里找到它:
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)
为了在每种类型的站点上执行此操作,这需要某种类型的URL源,它可以是预生成的URL的列表(可能是无限的),或者它可以是初始状态以及从其生成URL的东西(如果包含& page = 1,& page = 2等的网址,然后对于谷歌等真正搞砸的网页,提供一个初始网址,然后提供一个功能,搜索正文以查找下一个链接,然后使用该功能.您的站点使数据类型成为SiteEnum的实例,并为Result提供类型,该类型取决于站点,现在枚举器处理所有I / O,您不必考虑它.这很好用,我用它实现了一个站点.
我的问题是这个实现有一个烦恼是InputUrls数据类型.当我使用UrlFunc时,一切都是金色的.当我使用UrlSet或UrlPageDependent时,它并不是所有有趣的游戏,因为状态类型是未定义的,我必须将其强制转换为:: InputUrls()才能进行编译.这似乎是完全没必要的,因为该类型变量由于编写程序的方式,将永远不会用于大多数站点,但我不知道如何解决它.我发现我想在很多不同的上下文中使用这样的类型,并且我总是最终得到只在数据类型的某些部分中需要的杂散类型变量,但它不觉得我应该使用就是这样.有没有更好的方法呢?
最佳答案 为什么你需要UrlFunc案件呢?根据我的理解,你使用状态函数做的唯一事情是使用它来构建类似于UrlSet中的列表,所以不是存储状态函数,而是存储结果列表.这样,您可以从数据类型中消除状态类型变量,这样可以消除模糊问题.