Я столкнулся с проблемой взаимной рекурсии.Базовая структура, которую я использовал, состоит в том, что у меня есть модуль, который определяет класс типа, и несколько модулей, которые определяют экземпляры этого класса типа.Однако каждый экземпляр определяется в терминах всех других экземпляров.
Если это описание слишком абстрактное, то здесь приведен код, имеющий структуру, подобную моему коду.(Я немного урезал его, чтобы сделать необходимые биты очевидными, и добавил несколько эллипсов к частям, которые не имеют отношения к общей структуре).
Мой класс выглядит следующим образом:
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) = ...
Теперь я мог бы просто решить эту проблему, поместив все мои экземпляры в один модуль, однако вместо 2, показанного в моем примереУ меня есть 8 случаев, которые все взаимно рекурсивны друг с другом.Кроме того, каждый экземпляр довольно большой.Это означает, что полученный модуль будет огромным неуязвимым беспорядком.
Теперь в haskell wiki есть два предложения для решения вопросов взаимной рекурсии, но оба они на самом деле больше относятся к взаимно рекурсивным типам и ни к одному изони будут работать здесь.
Есть ли способ обойти эту взаимную рекурсию без простого объединения всех моих модулей?