fixIO

Apr. 6th, 2009 07:13 pm
lomeo: (лямбда)
[personal profile] lomeo
Предыстория: http://thesz.livejournal.com/950788.html?thread=7471620#t7471620

Т.е. предполагалось, что любой mdo можно развернуть в letrec (т.е. do без mfix).

Однако, простой пример
mdo
    tid1 <- forkOS (print tid2)
    tid2 <- forkOS (print tid1)
    return ()

будет в зависимости от настроения то выводить ThreadId, то показывать <<loop>>. Всё потому, что для хранения переменной используется IORef. Можно переписать mfix для IO, используя MVar:
newtype MyIO a = MyIO { runMyIO :: IO a }
    deriving (Functor, Monad, MonadIO)

instance MonadFix MyIO where
    mfix f = MyIO $ do
        ref <- newEmptyMVar
        vars <- unsafeInterleaveIO $ takeMVar ref
        realVars <- runMyIO $ f vars
        putMVar ref realVars
        return realVars

Тогда вместо <<loop>> просто висим в ожидании MVar. Зато наш пример начинает работать по человечески всегда:
myMain :: MyIO ()
myMain = mdo
    tid1 <- liftIO $ forkOS (print tid2)
    tid2 <- liftIO $ forkOS (print tid1)
    return ()

Какие могут быть подводные камни у такой реализации?

Ну, и самое главное. Я наконец понял, что перевести mdo в letrec не всегда возможно. Например, здесь. Если мы просто завернём все tid в монаду, то получим дли-и-и-инную цепочку thunk-ов, которую не сможем развернуть - stack overflow, однако! Если мы сделаем IO ленивым (тот же unsafeInterleaveIO), то получим многократное выполнение. Т.е. нам придётся вернуться к реализации ленивого IO с сохранением результата через какую нибудь изменяемую переменную. Ленивый - чтобы не зациклилось, сохранять результат - чтобы не перезапускалось.
From:
Anonymous( )Anonymous This account has disabled anonymous posting.
OpenID( )OpenID You can comment on this post while signed in with an account from many other sites, once you have confirmed your email address. Sign in using OpenID.
User
Account name:
Password:
If you don't have an account you can create one now.
Subject:
HTML doesn't work in the subject.

Message:

 
Notice: This account is set to log the IP addresses of everyone who comments.
Links will be displayed as unclickable URLs to help prevent spam.

Profile

lomeo: (Default)
Dmitry Antonyuk

December 2015

S M T W T F S
  12345
6789101112
131415 16171819
20212223242526
2728293031  

Most Popular Tags

Style Credit

Expand Cut Tags

No cut tags
Page generated Sep. 23rd, 2017 03:44 am
Powered by Dreamwidth Studios