代数数据类型的特定用例

  • 本文关键字:代数数据类型 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)

为了每一种类型的网站上,这需要一个url的一些来源,这可能是pregenerated url的列表(可能是无限的),也可以是一个初始状态,从它生成的url(比如url包含和页面= 1,和页面= 2,等等),然后像谷歌真的搞砸了页面,给一个初始url,然后提供一个函数,将身体寻找下一个链接,然后使用。你的站点使一个数据类型SiteEnum的实例,并给出一个类型的结果,这是网站依赖,现在枚举处理所有的I/O,你不必考虑它。这工作完美,我实现了一个网站与它。

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

为什么需要UrlFunc案例?据我所知,你对状态函数所做的唯一的事情就是用它来建立一个像UrlSet中那样的列表,所以不是存储状态函数,而是存储结果列表。这样,就可以从数据类型中消除state类型变量,从而消除歧义问题。

最新更新