Дон ответил на вопрос как на вопрос, но чуть более интересный вопрос - как поступить с
data Foo = Foo (MVar Bar) String
data Bar = Bar (MVar Foo) String
Теперь два MVars - не просто свидетели рекурсии, они сообщники.
Это может быть сделано двумя способами:
1.) Либо делая то, что вы делаете на императивном языке, таком как C:
mutation = do
-- setting up an empty mvar
bar <- newEmptyMVar
foo <- newMVar (Foo bar "foo")
-- and then filling it in
putMVar bar (Bar foo "foo")
return (foo, bar)
2.), Либо используя DoRec (ранее RecursiveDo) и mfix
, а за кулисами завязываем узел:
{-# LANGUAGE DoRec #-}
mutual = do
rec foo <- newMVar (Foo bar "foo")
bar <- newMVar (Bar foo "foo")
return (foo, bar)
Это означает нечто аналогичное:
mutual = do
(foo, bar) <- mfix $ \(foo, bar) -> do
foo <- newMVar (Foo bar "foo")
bar <- newMVar (Bar foo "foo")
return (foo, bar)
return (foo, bar)