I am running into a mutual recursion issue. The basic structure I have employed is that I have a module that defines a type class and several modules that define instances of that type class. Each instance however is defined in terms of all the other instances.
If that description is a little too abstract here is some code that has a structure like my code. (I've trimmed it down quite a bit to make the necessary bits obvious and added some ellipses to parts that are not relevant to the overall structure).
My class looks like the following:
data Result = ...
class Foo a where
openFoo :: Result -> IO (a, Result)
runFoo :: (a, Result) -> IO (a, Result)
closeFoo :: (a, Result) -> IO Result
Then I have the instances
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) = ...
Now I could simply resolve this by putting all of my instances into a single module, however rather than the 2 shown in my example I have 8 instances that are all mutually recursive with each other. On top of that each instance is quite large. Meaning the resulting module would be an enormous innavigable mess.
Now the haskell wiki has two suggestion for solving mutual recursion issues, but both of them are really more about mutually recursive types and neither of them is going to work here.
Is there anyway to get around this mutual recursion without simply combining all of my modules?