我遇到了一个相互递归的问题。我采用的基本结构是我有一个定义类型类的模块和几个定义该类型类实例的模块。然而,每个实例都是根据所有其他实例定义的。
如果该描述有点过于抽象,这里有一些代码,其结构类似于我的代码。(我已经把它剪掉了很多,以使必要的部分变得明显,并在与整体结构无关的部分添加了一些省略号)。
我的课程如下所示:
data Result = ...
class Foo a where
openFoo :: Result -> IO (a, Result)
runFoo :: (a, Result) -> IO (a, Result)
closeFoo :: (a, Result) -> IO Result
然后我有实例
data XData = ...
instance Foo XData where
openFoo result = ...
runFoo (data, result) = do
currentEvent <- getEvent
case currentEvent of
EventA -> return (data, result)
EventB ->
(openFoo result :: IO YData)
>>= runFoo
>>= closeFoo
>>= curry return data
closeFoo (data, result) = ...
data YData = ...
instance Foo YData where
openFoo result = ...
runFoo (data, result) = do
currentEvent <- getEvent
case currentEvent of
EventA -> return (data, result)
EventB ->
(openFoo result :: IO XData)
>>= runFoo
>>= closeFoo
>>= curry return data
closeFoo (data, result) = ...
现在我可以通过将所有实例放入单个模块来简单地解决这个问题,但是我有 8 个实例,而不是我的示例中显示的 2 个实例,它们都是相互递归的。最重要的是,每个实例都非常大。这意味着生成的模块将是一个巨大的无法导航的混乱。
现在,haskell wiki 有两个解决相互递归问题的建议,但它们实际上更多的是关于相互递归类型,并且它们都不会在这里工作。
无论如何,如果不简单地组合我的所有模块,是否可以绕过这种相互递归?