Sri*_*aic 6 haskell mutual-recursion
我遇到了一个相互递归的问题。我采用的基本结构是,我有一个定义类型类的模块和几个定义该类型类实例的模块。但是,根据所有其他实例来定义每个实例。
如果说的描述太抽象了,那么这里有一些代码的结构类似于我的代码。(我已对其进行了相当大的削减,以使必要的部分变得明显,并在与整体结构无关的部分上添加了一些椭圆形)。
我的课程如下所示:
data Result = ...
class Foo a where
openFoo :: Result -> IO (a, Result)
runFoo :: (a, Result) -> IO (a, Result)
closeFoo :: (a, Result) -> IO Result
Run Code Online (Sandbox Code Playgroud)
然后我有实例
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) = ...
Run Code Online (Sandbox Code Playgroud)
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) = ...
Run Code Online (Sandbox Code Playgroud)
现在,我可以通过将所有实例放入一个模块中来简单地解决此问题,但是与示例中所示的2个实例不同,我有8个实例,它们彼此相互递归。最重要的是,每个实例都很大。这意味着生成的模块将是一个巨大的无法解决的混乱。
现在,haskell Wiki提出了两个解决相互递归问题的建议,但是它们实际上都更多地涉及相互递归类型,并且它们都不在这里起作用。
有没有解决这个相互递归而不简单地结合我所有的模块?
这是一种稍微有点老套的方法。首先,将递归定义放在一个模块中:
module Internal.Recursive
data XData = ...
data YData = ...
-- Recursive definitions...
Run Code Online (Sandbox Code Playgroud)
然后从单独的模块重新导出每个定义:
module XData (IR.XData) where
import qualified Internal.Recursive as IR
Run Code Online (Sandbox Code Playgroud)
module YData (IR.XYata) where
import qualified Internal.Recursive as IR
Run Code Online (Sandbox Code Playgroud)
这将给出相互递归模块的外观。(我不相信 GHC 允许任何简单的方法来制作实际的递归模块。)