Haskell 代数数据类型的特定用例

Haskell 代数数据类型的特定用例,haskell,Haskell,我写了一个通用的枚举器,作为一个练习来刮网站,我做到了,它是完整的,运行良好,但我有一个问题。你可以在这里找到它:如果你想看看代码 基本思想是我想要一个枚举器,它在搜索引擎、博客、你必须获取页面的地方,以及它将有25个条目,你需要一个条目一次。但同时我不想为每个站点编写管道,所以我想要一个通用接口。我想到的是(这使用类型族): 为了在每种类型的站点上实现这一点,这需要某种url源,可以是预生成url的列表(可能是无限的),也可以是初始状态,并从中生成url(例如,如果url包含&page=1,&

我写了一个通用的枚举器,作为一个练习来刮网站,我做到了,它是完整的,运行良好,但我有一个问题。你可以在这里找到它:如果你想看看代码

基本思想是我想要一个枚举器,它在搜索引擎、博客、你必须获取页面的地方,以及它将有25个条目,你需要一个条目一次。但同时我不想为每个站点编写管道,所以我想要一个通用接口。我想到的是(这使用类型族):

为了在每种类型的站点上实现这一点,这需要某种url源,可以是预生成url的列表(可能是无限的),也可以是初始状态,并从中生成url(例如,如果url包含&page=1,&page=2等),然后对于像google这样的真正糟糕的页面,给出一个初始url,然后提供一个函数,该函数将在正文中搜索下一个链接,然后使用该链接。您的站点将一个数据类型作为SiteEnum的实例,并为结果提供一个依赖于站点的类型,现在枚举器处理所有I/O,您不必考虑它。这是完美的,我用它实现了一个站点


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

为什么需要
UrlFunc
案例?据我所知,使用state函数所做的唯一一件事就是使用它构建一个列表,就像
UrlSet
中的列表一样,因此不存储state函数,只存储结果列表。这样,您就可以从数据类型中删除
state
type变量,这应该可以消除歧义问题。

我建议您在标题上做一点工作:)我需要一个建议,我不知道该怎么称呼它。我想说“这不是重点,我需要它的地方还有其他问题”,但我越想越想,我越是意识到我其实并不需要它们。在类型级别上使用这个函数的变量部分是完全不必要的,在这种情况下,我想不出有什么理由使用它,所以我删除了urlFunc,我将在以后的项目中记住这一课。在本例中,它最终是对源代码的最小更改。
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)