рд╣рд╛рд╕реНрдХреЗрд▓ред рдмрд╣реБ-рдереНрд░реЗрдбреЗрдб рдЕрдиреБрдкреНрд░рдпреЛрдЧ рдХрд╛ рдкрд░реАрдХреНрд╖рдг

рдпрд╣ рд▓реЗрдЦ рдЕрдХрд╛рджрдорд┐рдХ рд╡рд┐рд╢реНрд╡рд╡рд┐рджреНрдпрд╛рд▓рдп рд╡рд╛рд▓реЗрд░реА рдЗрд╕реЗрд╡ рдХреЗ рд╡реНрдпрд╛рдЦреНрдпрд╛рддрд╛ рджреНрд╡рд╛рд░рд╛ рдХрд╛рд░реНрдпрд╛рддреНрдордХ рдкреНрд░реЛрдЧреНрд░рд╛рдорд┐рдВрдЧ рдкрд╛рдареНрдпрдХреНрд░рдо рдХреЗ рд▓рд┐рдП рдЕрднреНрдпрд╛рд╕ рд╕рд╛рдордЧреНрд░реА рдХреЗ рдЖрдзрд╛рд░ рдкрд░ рд╕рдВрдХрд▓рд┐рдд рдХрд┐рдпрд╛ рдЧрдпрд╛ рдерд╛ред

рдореЗрд░рд╛ рдорд╛рдирдирд╛ тАЛтАЛрд╣реИ рдХрд┐ рдпрд╣ рдХрд┐рд╕реА рдХреЗ рд▓рд┐рдП рдХреЛрдИ рд░рд╣рд╕реНрдп рдирд╣реАрдВ рд╣реИ рдХрд┐ рдорд▓реНрдЯреАрдереНрд░реЗрдбреЗрдб рдПрдкреНрд▓рд┐рдХреЗрд╢рди рд▓рд┐рдЦрдирд╛ рдХрдИ рд╕рдорд╕реНрдпрд╛рдУрдВ рд╕реЗ рдЬреБрдбрд╝рд╛ рд╣реИ рдЬреЛ рдПрдХрд▓-рдереНрд░реЗрдбреЗрдб рдкреНрд░реЛрдЧреНрд░рд╛рдо рдХреЗ рд╡рд┐рдХрд╛рд╕ рдореЗрдВ рдЕрдиреБрдкрд╕реНрдерд┐рдд рд╣реИрдВред
рдПрдХ рд╕рдорд╕реНрдпрд╛ рдЕрдиреБрдкреНрд░рдпреЛрдЧ рдХрд╛ рдкрд░реАрдХреНрд╖рдг рдХрд░ рд░рд╣реА рд╣реИред
рд╣рдо рдЙрд╕ рдХреНрд░рдо рдХреЛ рдирд┐рдпрдВрддреНрд░рд┐рдд рдирд╣реАрдВ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ рдЬрд┐рд╕рдореЗрдВ рд╕рдВрдЪрд╛рд▓рди рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ; рдЗрд╕рд▓рд┐рдП, рдХрд╛рд░реНрдпрдХреНрд░рдо рдирд┐рд╖реНрдкрд╛рджрди рдХрд╛ рдкрд░рд┐рдгрд╛рдо рднреА рдирд┐рдпрдВрддреНрд░рд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЙрддреНрддрд░рджрд╛рдпреА рдирд╣реАрдВ рд╣реИред рдпрд╣рд╛рдВ рддрдХ тАЛтАЛрдХрд┐ рдЕрдЧрд░ рд╣рдореЗрдВ рдХреЛрдИ рддреНрд░реБрдЯрд┐ рдорд┐рд▓рддреА рд╣реИ, рддреЛ рджреВрд╕рд░реА рдмрд╛рд░ рдЙрд╕реА рд░реЗрдХ рдкрд░ рдХрджрдо рд░рдЦрдирд╛ рдЗрддрдирд╛ рдЖрд╕рд╛рди рдирд╣реАрдВ рд╣реЛрдЧрд╛ред
рдореИрдВ рдПрдХ multithreaded рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдХрд╛ рдкрд░реАрдХреНрд╖рдг рдХрд░рдиреЗ рдХреЗ рддрд░реАрдХреЗ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдПрдХ рдЫреЛрдЯрд╛ рд╕рд╛ рдиреБрд╕реНрдЦрд╛ рджреЗрдирд╛ рдЪрд╛рд╣рддрд╛ рд╣реВрдВред
рд╣рдореЗрдВ рдЬрд┐рди рд╕рд╛рдордЧреНрд░рд┐рдпреЛрдВ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрддреА рд╣реИ рдЙрдирдореЗрдВ: haskell , QuickCheck , рдХреБрдЫ рдореЛрдирд╛рдбреНрд╕, рдирдордХ / рдХрд╛рд▓реА рдорд┐рд░реНрдЪ рд╕реНрд╡рд╛рдж рдХреЗ рд▓рд┐рдПред

рдХрд╛рдо рдХрд░рдиреЗ рдХрд╛ рдЙрджрд╛рд╣рд░рдг


рдПрдХ рдХрд╛рдо рдХреЗ рдЙрджрд╛рд╣рд░рдг рдХреЗ рд░реВрдк рдореЗрдВ, рд╣рдо рднреЛрдЬрди рджрд╛рд░реНрд╢рдирд┐рдХреЛрдВ рдХреА рд╕рдорд╕реНрдпрд╛ рдХреЛ рд▓реЗрддреЗ рд╣реИрдВред

MVar a рдРрд╕рд╛ рд╕рдВрджрд░реНрдн рд╣реИ рдЬрд┐рд╕рдореЗрдВ рдпрд╛ рддреЛ рдЯрд╛рдЗрдк рдХрд╛ рдорд╛рди рд╣реЛрддрд╛ рд╣реИ рдпрд╛ рдЦрд╛рд▓реА рд╣реЛрддрд╛ рд╣реИред
putMVar ref x рд░реЗрдлрд░реА рд▓рд┐рдВрдХ рдкрд░ рд╡реИрд▓реНрдпреВ putMVar ref x рдбрд╛рд▓рддрд╛ рд╣реИред
takeMVar ref рд▓рд┐рдВрдХ рдХреА рд╕рд╛рдордЧреНрд░реА рдХреЛ рдкрдврд╝рддрд╛ рд╣реИ, рдЗрд╕рдХреЗ рдмрд╛рдж рдЗрд╕реЗ рдЦрд╛рд▓реА рдЫреЛрдбрд╝ рджреЗрддрд╛ рд╣реИред
рдпрджрд┐ рдпрд╣ рдкрд╣рд▓реЗ рд╕реЗ рд╣реА рдЦрд╛рд▓реА рдерд╛, рддреЛ рдзрд╛рд░рд╛ рд╕реЛ рдЬрд╛рддреА рд╣реИ рдЬрдм рддрдХ рдХрд┐ рдХреБрдЫ рдФрд░ рдЗрд╕реЗ рдирд╣реАрдВ рд▓рд┐рдЦрддрд╛ред
() рдПрдХ рдкреНрд░рдХрд╛рд░ рд╣реИ рдЬрд┐рд╕рдХрд╛ рдПрдХрд▓ рдорд╛рди рд╣реИ, рдЬрд┐рд╕реЗ рдЙрд╕реА рдкреНрд░рдХрд╛рд░ рд╕реЗ рджрд░реНрд╢рд╛рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ рдЬреИрд╕реЗ - () ред
рд╣рдо MVar () рдЬреИрд╕реЗ рд▓рд┐рдВрдХ рдХреЗ рд╕рд╛рде рдХрд╛рдВрдЯреЗ MVar () ред
рдЗрд╕ рдкреНрд░рдХрд╛рд░, рдПрдХ рдХрд╛рдВрдЯрд╛ рдореЗрдВ рджреЛ рд░рд╛рдЬреНрдп рд╣реЛ рд╕рдХрддреЗ рд╣реИрдВ: рдпрджрд┐ рдХрд┐рд╕реА рднреА рджрд╛рд░реНрд╢рдирд┐рдХ рджреНрд╡рд╛рд░рд╛ рдХрд╛рдВрдЯрд╛ рдкрд░ рдХрдмреНрдЬрд╛ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рддреЛ рдпрд╣ рдЦрд╛рд▓реА рд╣реИ; рдпрджрд┐ рдкреНрд▓рдЧ рдореБрдХреНрдд рд╣реИ, рддреЛ рдЗрд╕рдореЗрдВ рдореВрд▓реНрдп () ред

 import System.Random import Control.Monad import Control.Concurrent import Control.Monad.Cont import Control.Monad.Trans import Data.IORef import Test.QuickCheck import Test.QuickCheck.Gen import Test.QuickCheck.Monadic -- sleep       ( 0  0.3) sleep :: IO () sleep = randomRIO (0, 300000) >>= threadDelay phil :: Int --  . -> MVar () --    . -> MVar () --    . -> IO () phil n leftFork rightFork = forever $ do putStrLn $ show n ++ " is awaiting" sleep takeMVar leftFork putStrLn $ show n ++ " took left fork" -- sleep takeMVar rightFork putStrLn $ show n ++ " took right fork" sleep putMVar leftFork () putMVar rightFork () putStrLn $ show n ++ " put forks" sleep runPhil :: Int -> IO () runPhil n = do --  ,   . forks <- replicateM n $ newMVar () --  5 ,     phil. forM_ [1..n] $ \i -> forkIO $ phil i (forks !! (i - 1)) (forks !! (i `mod` n)) main = do runPhil 5 --    ,  ,     . forever (threadDelay 1000000000) 

рдЗрд╕ рдХрд╛рд░реНрдпрдХреНрд░рдо рдореЗрдВ рдЧрддрд┐рд░реЛрдз рд╣реЛ рд╕рдХрддрд╛ рд╣реИред
рдЗрд╕рдХрд╛ рдЖрдирдВрдж рд▓реЗрдиреЗ рдХреЗ рд▓рд┐рдП, рдЖрдк рд▓рд╛рдЗрди рдХреЛ рдЕрд╕рд╣рдЬ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ - sleep рдФрд░ рдереЛрдбрд╝рд╛ рдЗрдВрддрдЬрд╛рд░ рдХрд░реЛред
рд╣рдорд╛рд░рд╛ рд▓рдХреНрд╖реНрдп рдкрд░реАрдХреНрд╖рдг рд▓рд┐рдЦрдирд╛ рд╣реИ рдЬреЛ рдЗрд╕ рддреНрд░реБрдЯрд┐ рдХрд╛ рдкрддрд╛ рд▓рдЧрд╛рдПрдЧрд╛ред
рд▓реЗрдХрд┐рди рдЗрд╕рд╕реЗ рдкрд╣рд▓реЗ рдХрд┐ рд╣рдо рдРрд╕рд╛ рдХрд░ рд╕рдХреЗрдВ, рдпрд╣ рд╕рдордЭрдиреЗ рд▓рд╛рдпрдХ рд╣реИ рдХрд┐ рд╣рдо рд╕рдВрдЪрд╛рд▓рди рдХреЗ рдХреНрд░рдо рдХреЛ рдХреИрд╕реЗ рдкреНрд░рдмрдВрдзрд┐рдд рдХрд░реЗрдВрдЧреЗред рдЗрд╕рдХреЗ рд▓рд┐рдП, IO рдХреЗ рдмрдЬрд╛рдп, рд╣рдо рдПрдХ рдФрд░ monad рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реИрдВред

рд╣рдо sleep , phil рдФрд░ runPhil рдХреА рдкрд░рд┐рднрд╛рд╖рд╛ рдХреЛ рд╕рдВрдХреНрд╖реЗрдк рдореЗрдВ рдкреНрд░рд╕реНрддреБрдд рдХрд░рддреЗ рд╣реИрдВ рддрд╛рдХрд┐ рд╡реЗ рдЕрдиреНрдп runPhil рд▓рд┐рдП рднреА рдХрд╛рдо рдХрд░реЗрдВред

 sleep :: MonadIO m => m () sleep = do r <- liftIO $ randomRIO (0, 100) r `times` liftIO (threadDelay 300) where times :: Monad m => Int -> m () -> m () times ra = mapM_ (\_ -> a) [1..r] 

рдЕрдм sleep рд╕рдорд╛рд░реЛрд╣ рдХрд┐рд╕реА рднреА рдореЛрдиреЛрдб рдХреЗ рд╕рд╛рде рдХрд╛рдо рдХрд░ рд╕рдХрддрд╛ рд╣реИ рдЬреЛ IO рд╕рдВрдЪрд╛рд▓рди рдХрд╛ рд╕рдорд░реНрдерди рдХрд░рддрд╛ рд╣реИред MonadIO рд╡рд░реНрдЧ рдореЗрдВ, рдХреЗрд╡рд▓ рдПрдХ liftIO рдлрд╝рдВрдХреНрд╢рди рдХреЛ liftIO рдЬрд╛рддрд╛ liftIO рдЬреЛ рдЗрд╕реЗ рдЕрдиреБрдорддрд┐ рджреЗрддрд╛ рд╣реИред
рдзреНрдпрд╛рди рджреЗрдВ рдХрд┐ рдпрд╛рджреГрдЪреНрдЫрд┐рдХ рд╕рдВрдЦреНрдпрд╛ рдореЗрдВ рдПрдХ рдмрд╛рд░ рд╕реЛ рдЬрд╛рдиреЗ рдХреЗ рдмрдЬрд╛рдп, рд╣рдо 0.3 рдорд┐рд▓реАрд╕реЗрдХрдВрдб рдХреЗ рд▓рд┐рдП рдпрд╛рджреГрдЪреНрдЫрд┐рдХ рд╕рдВрдЦреНрдпрд╛ рдореЗрдВ рд╕реЛ рдЬрд╛рддреЗ рд╣реИрдВред рдХрд╛рд░рдг рдпрд╣ рд╣реИ рдХрд┐ рд╣рдорд╛рд░реЗ liftIO , liftIO рдЕрдВрджрд░ рдХреА рдХреНрд░рд┐рдпрд╛рдПрдВ рдкрд░рдорд╛рдгреБ рд░реВрдк рд╕реЗ рдХреА рдЬрд╛рддреА рд╣реИрдВред рддрджрдиреБрд╕рд╛рд░, рдЬреЛ рд╕рдордп рд╣рдо рд╕реЛрддреЗ рд╣реИрдВ рд╡рд╣ рдХрд┐рд╕реА рднреА рдЪреАрдЬ рдХреЛ рдкреНрд░рднрд╛рд╡рд┐рдд рдирд╣реАрдВ рдХрд░рддрд╛ рд╣реИ, рдпрд╣ рдХреЗрд╡рд▓ рдорд╣рддреНрд╡рдкреВрд░реНрдг рд╣реИ рдХрд┐ рд╣рдо рдЗрд╕реЗ рдХрд┐рддрдиреА рдмрд╛рд░ рдХрд░рддреЗ рд╣реИрдВред

рдЪреВрдВрдХрд┐ рд╣рдорд╛рд░рд╛ MVar рдПрдХ рдзрд╛рдЧреЗ рдореЗрдВ рдХрд╛рдо рдХрд░реЗрдЧрд╛, MVar рд╣рдорд╛рд░реЗ рд▓рд┐рдП рдмреЗрдХрд╛рд░ рд╣реИ, рдФрд░ рд╣рдо рдмрд╛рдж рдореЗрдВ рдЕрдкрдиреЗ рдкреНрд░рдХрд╛рд░ рдХреЗ рд▓рд┐рдВрдХ рдХреЛ рдкрд░рд┐рднрд╛рд╖рд┐рдд рдХрд░реЗрдВрдЧреЗ, рдЗрд╕ рддрдереНрдп рдХреЗ рдЖрдзрд╛рд░ рдкрд░ рдХрд┐ MVar рдФрд░ рдЕрдиреНрдп рдкреНрд░рдХрд╛рд░ рдХреЗ рд▓рд┐рдВрдХ рдХреЗ рд╕рд╛рде phil рдлрд╝рдВрдХреНрд╢рди рдХрд╛рдо рдХрд░ рд╕рдХрддрд╛ рд╣реИред
рдРрд╕рд╛ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рд╣рдо MonadConcurrent рдХреЛ рдкрд░рд┐рднрд╛рд╖рд┐рдд рдХрд░рддреЗ рд╣реИрдВ, рдЬрд┐рд╕рдореЗрдВ рд╕рдВрджрд░реНрдн рдмрдирд╛рдиреЗ, рдкрдврд╝рдиреЗ рдФрд░ рд▓рд┐рдЦрдиреЗ рдХреЗ рд╕рд╛рде-рд╕рд╛рде рдереНрд░реЗрдб рдмрдирд╛рдиреЗ рдХреЗ рд▓рд┐рдП рдСрдкрд░реЗрд╢рди рд╣реЛрдВрдЧреЗред

 class Monad m => MonadConcurrent m where type CVar m :: * -> * newCVar :: a -> m (CVar ma) takeCVar :: CVar ma -> ma putCVar :: CVar ma -> a -> m () fork :: m () -> m () 


рдпрд╣рд╛рдВ рд╣рдордиреЗ рдЯрд╛рдЗрдк рдкрд░рд┐рд╡рд╛рд░реЛрдВ рдХрд╛ рдЗрд╕реНрддреЗрдорд╛рд▓ рдХрд┐рдпрд╛, рдЬреЛ рднрд╛рд╖рд╛ рдХрд╛ рд╡рд┐рд╕реНрддрд╛рд░ рд╣реИрдВред
рдЗрд╕ рдорд╛рдорд▓реЗ рдореЗрдВ, рд╣рдореЗрдВ рдЗрд╕ рд╡рд┐рд╕реНрддрд╛рд░ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ рддрд╛рдХрд┐ рд╣рдо рд╡рд┐рднрд┐рдиреНрди рд╕рд╛рдзреБрдУрдВ рдХреЗ рд▓рд┐рдП рд╡рд┐рднрд┐рдиреНрди рдкреНрд░рдХрд╛рд░ рдХреЗ рд▓рд┐рдВрдХ рдкрд░рд┐рднрд╛рд╖рд┐рдд рдХрд░ рд╕рдХреЗрдВред
рдПрдХреНрд╕рдЯреЗрдВрд╢рди рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рдЖрдкрдХреЛ рдлрд╝рд╛рдЗрд▓ рдХреА рд╢реБрд░реБрдЖрдд рдореЗрдВ рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рдкрдВрдХреНрддрд┐ рдХреЛ рдЬреЛрдбрд╝рдирд╛ рд╣реЛрдЧрд╛ (рдФрд░ рдЙрд╕реА рд╕рдордп рдЙрди рдПрдХреНрд╕рдЯреЗрдВрд╢рдиреЛрдВ рдХреЛ рдХрдиреЗрдХреНрдЯ рдХрд░реЗрдВ рдЬрд┐рдирдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрдЧреА):

 {-# LANGUAGE TypeFamilies, ExistentialQuantification, GeneralizedNewtypeDeriving #-} 

IO рд╕рдирдХ рдХреЗ рд▓рд┐рдП рдЗрд╕ рд╡рд░реНрдЧ рдХреЗ рдПрдХ instance рдкрд░рд┐рднрд╛рд╖рд┐рдд рдХрд░реЗрдВред
рдпрд╣рд╛рдВ рд╕рдм рдХреБрдЫ рдЖрд╕рд╛рди рд╣реИ: рд╣рдо рд╕рд┐рд░реНрдл MVar рд▓рд┐рдП рдЙрдкрдпреБрдХреНрдд рд╕рдВрдЪрд╛рд▓рди рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реИрдВред

 instance MonadConcurrent IO where type CVar IO = MVar newCVar = newMVar takeCVar = takeMVar putCVar = putMVar fork m = forkIO m >> return () 

рдХрд╛рд░реНрдпреЛрдВ рдХреЛ рд╕рд╛рд░рд╛рдВрд╢рд┐рдд рдХрд░реЗрдВ рдФрд░ runPhil ред

 phil :: (MonadIO m, MonadConcurrent m) => Int -> CVar m () -> CVar m () -> m () phil n leftFork rightFork = forever $ do liftIO $ putStrLn $ show n ++ " is awaiting" sleep takeCVar leftFork liftIO $ putStrLn $ show n ++ " took left fork" takeCVar rightFork liftIO $ putStrLn $ show n ++ " took right fork" sleep putCVar leftFork () putCVar rightFork () liftIO $ putStrLn $ show n ++ " put forks" sleep runPhil :: (MonadIO m, MonadConcurrent m) => Int -> m () runPhil n = do forks <- replicateM n $ newCVar () forM_ [1..n] $ \i -> fork $ phil i (forks !! (i - 1)) (forks !! (i `mod` n)) 

рдкреНрд░реЛрдЧреНрд░рд╛рдо рдХреЛ рдЪрд▓рд╛рдПрдВ рдФрд░ рд╕реБрдирд┐рд╢реНрдЪрд┐рдд рдХрд░реЗрдВ рдХрд┐ рдпрд╣ рдкрд╣рд▓реЗ рдХреА рддрд░рд╣ рдХрд╛рдо рдХрд░рддрд╛ рд╣реИред

рдореЛрдирд╛рдб рд╕рдорд╡рд░реНрддреА


рдФрд░ рдЕрдм рдордЬрд╛ рд╢реБрд░реВ рд╣реЛрддрд╛ рд╣реИред

рдЙрд╕ рдореЛрдирд╛рдб рдХреЛ рдкрд░рд┐рднрд╛рд╖рд┐рдд рдХрд░реЗрдВ рдЬрд┐рд╕рдореЗрдВ рд╣рдо рдХрд╛рдо рдХрд░реЗрдВрдЧреЗ (рдЖрдЧреЗ рджреЗрдЦрддреЗ рд╣реБрдП, рдореИрдВ рдХрд╣реВрдВрдЧрд╛ рдХрд┐ рдЗрд╕реЗ Cont рдХрд╣рд╛ рдЬрд╛рддрд╛ рд╣реИ)ред рдореИрдВ рдпрд╣ рд╕реБрдЭрд╛рд╡ рджреЗрдиреЗ рдХреЗ рд▓рд┐рдП рднреА рдЙрджреНрдпрдо рдХрд░рддрд╛ рд╣реВрдВ рдХрд┐ Cont рдПрдХ рд╣реА рд╕рдордп рдореЗрдВ рд╕рдмрд╕реЗ рдЬрдЯрд┐рд▓ рдФрд░ рд╕рдмрд╕реЗ рд╢рдХреНрддрд┐рд╢рд╛рд▓реА рд╕рд╛рдзреБрдУрдВ рдореЗрдВ рд╕реЗ рдПрдХ рд╣реИред
рдЗрд╕ рд╕рдирдХ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реБрдП, рдЖрдк рдирд┐рдпрдВрддреНрд░рдг рдкреНрд░рд╡рд╛рд╣ рдХреЗ рд╕рд╛рде рдХреБрдЫ рднреА рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ: рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рдХреНрд░рд┐рдпрд╛ рдХрд░рдиреЗ рдХреЗ рдмрдЬрд╛рдп, рдЖрдк рдЙрдиреНрд╣реЗрдВ рдПрдХ рд╕рдВрд░рдЪрдирд╛ рдореЗрдВ рд╕рд╣реЗрдЬ рд╕рдХрддреЗ рд╣реИрдВ (рдЗрд╕ рдЙрджреНрджреЗрд╢реНрдп рдХреЗ рд▓рд┐рдП, рдПрдХ Action рдкреНрд░рдХрд╛рд░ рдШреЛрд╖рд┐рдд рдХрд░реЗрдВ) рдФрд░ рдЙрдиреНрд╣реЗрдВ рдмрд╛рдж рдореЗрдВ рдирд┐рд╖реНрдкрд╛рджрд┐рдд рдХрд░реЗрдВ, рд╕рдВрднрд╡рддрдГ рдПрдХ рдЕрд▓рдЧ рдХреНрд░рдо рдореЗрдВред

 data Action = Atom (IO Action) | forall a. ReadRef (MaybeRef a) (a -> Action) | forall a. WriteRef (MaybeRef a) a Action | Fork Action Action | Stop 

рдЖрдЗрдП рдкреНрд░рддреНрдпреЗрдХ рдирд┐рд░реНрдорд╛рддрд╛ рдХреЗ рд╕рд╛рде рдЕрд▓рдЧ рд╕реЗ рд╡реНрдпрд╡рд╣рд╛рд░ рдХрд░реЗрдВред
Stop рдПрдХреНрд╢рди рдХрд╛ рдорддрд▓рдм рд╣реИ рдХрд┐ рдЧрдгрдирд╛ рдкреВрд░реА рд╣реЛ рдЧрдИ рд╣реИред
Fork рдХрд╛рд░реНрд░рд╡рд╛рдИ рдХрд╛ рдЕрд░реНрде рд╣реИ рдХрд┐ рдЧрдгрдирд╛ рд╢рд╛рдЦрд╛, рдпрд╛рдиреА рдЕрдм рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рджреЛ рдзрд╛рдЧреЗ рд╣реИрдВ рдЬрд┐рдиреНрд╣реЗрдВ рдПрдХ рд╕рд╛рде рдирд┐рд╖реНрдкрд╛рджрд┐рдд рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИред
Atom рдПрдХреНрд╢рди рдПрдХ рдкрд░рдорд╛рдгреБ рдЖрдИрдУ рдСрдкрд░реЗрд╢рди рдХрд░рддрд╛ рд╣реИ, рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рдирдпрд╛ Action рд╣реЛрддрд╛ рд╣реИ рдЬрд┐рд╕рдореЗрдВ рдПрдХреНрд╢рди рд╣реЛрддрд╛ рд╣реИ, рдЬрд┐рд╕реЗ рдЕрдЧрд▓реЗ рдЪрд░рдг рдореЗрдВ рдХрд┐рдпрд╛ рдЬрд╛рдирд╛ рдЪрд╛рд╣рд┐рдПред

рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП:
getSum рдлрд╝рдВрдХреНрд╢рди рдПрдХ рдХреНрд░рд┐рдпрд╛ рдХреЛ рдкрд░рд┐рднрд╛рд╖рд┐рдд рдХрд░рддрд╛ рд╣реИ рдЬреЛ рдХреАрдмреЛрд░реНрдб рд╕реЗ рджреЛ рдирдВрдмрд░ рдкрдврд╝рддрд╛ рд╣реИ, рдЙрдирдХреА рд░рд╛рд╢рд┐ рдкреНрд░рд┐рдВрдЯ рдХрд░рддрд╛ рд╣реИ, рдФрд░ рд╕рдорд╛рдкреНрдд рд╣реЛрддрд╛ рд╣реИред

 getSum :: Action getSum = Atom $ do x <- readLn --    return $ Atom $ do --   y <- readLn --    return $ Atom $ do --   print (x + y) --   return Stop --   

рдЕрдЧрд▓рд╛:
WriteRef ref val act рдПрдХреНрд╢рди WriteRef ref val act ref рд▓рд┐рдВрдХ рдкрд░ val рдХреЗ рдореВрд▓реНрдп рдХреЛ рд░рд┐рдХреЙрд░реНрдб рдХрд░рддрд╛ рд╣реИ, рдирд┐рд░рдВрддрд░рддрд╛ act ред
ReadRef ref act рдХрд╛рд░реНрд░рд╡рд╛рдИ ReadRef ref act рд╕рдВрджрд░реНрдн ref рджреНрд╡рд╛рд░рд╛ рдореВрд▓реНрдп рдкрдврд╝рддрд╛ рд╣реИ, act рдЗрд╕ рдореВрд▓реНрдп рдХреЛ рд▓реЗрддрд╛ рд╣реИ рдФрд░ рдПрдХ рдирд┐рд░рдВрддрд░рддрд╛ рджреЗрддрд╛ рд╣реИред
рддрд╛рдХрд┐ Action рдЖрдк рдЕрдирд┐рдпрдВрддреНрд░рд┐рдд рдкреНрд░рдХрд╛рд░ рдХреЗ рд▓рд┐рдВрдХ рдХреЛ рдмрдЪрд╛ рд╕рдХреЗрдВ, рд╣рдо рднрд╛рд╖рд╛ рдХреЗ рдПрдХ рдФрд░ рд╡рд┐рд╕реНрддрд╛рд░ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реИрдВ - рдЕрд╕реНрддрд┐рддреНрд╡рдЧрдд рдорд╛рддреНрд░рд╛ рдХрд╛ рдард╣рд░рд╛рд╡ред

MaybeRef рдкреНрд░рдХрд╛рд░ рдЙрди рд▓рд┐рдВрдХ рдХреЗ рдкреНрд░рдХрд╛рд░ рдХрд╛ рдкреНрд░рддрд┐рдирд┐рдзрд┐рддреНрд╡ рдХрд░рддрд╛ рд╣реИ, MVar рдЙрдкрдпреЛрдЧ рд╣рдо MVar рдмрдЬрд╛рдп рдХрд░реЗрдВрдЧреЗ, рдФрд░ рдЗрд╕реЗ Maybe рд╕рдВрджрд░реНрдн рдХреЗ рд░реВрдк рдореЗрдВ рдкрд░рд┐рднрд╛рд╖рд┐рдд рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИред

 newtype MaybeRef a = MaybeRef (IORef (Maybe a)) 

рдЕрдм рд╣рдо рдЕрдкрдиреЗ рдорда рдХреЛ рдкрд░рд┐рднрд╛рд╖рд┐рдд рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред
рдЬреИрд╕рд╛ рдХрд┐ рдореИрдВрдиреЗ рд╡рд╛рджрд╛ рдХрд┐рдпрд╛ рдерд╛, рд╣рдо рд╕рд┐рд░реНрдл Cont рдореЛрдирдб рд▓рдкреЗрдЯрддреЗ рд╣реИрдВред

 newtype Concurrent a = Concurrent (Cont Action a) deriving Monad 

Cont Action рдореЛрдирдб рдХрд╛ рдЖрдпреЛрдЬрди рдирд┐рдореНрдирд╛рдиреБрд╕рд╛рд░ рд╣реИред
рдПрдХ рдкреНрд░рдХрд╛рд░ рдХреЗ рдорд╛рди рдХреЛ рд╡рд╛рдкрд╕ рдХрд░рдиреЗ рдХреЗ рдмрдЬрд╛рдп, рдпрд╣ рдкреНрд░рдХрд╛рд░ (a -> Action) рдХреА рдирд┐рд░рдВрддрд░рддрд╛ рд▓реЗрддрд╛ рд╣реИ, рдЗрд╕ рдлрд╝рдВрдХреНрд╢рди рдХреЗ рд▓рд┐рдП рдПрдХ рдорд╛рди рдкрд╛рд░рд┐рдд рдХрд░рддрд╛ рд╣реИ, рдФрд░ рдкрд░рд┐рдгрд╛рдо рд▓реМрдЯрд╛рддрд╛ рд╣реИред
рдЕрд░реНрдерд╛рддреН, рд╣рдо рдпрд╣ рдорд╛рди рд╕рдХрддреЗ рд╣реИрдВ рдХрд┐ Cont Action a = (a -> Action) -> Action ред
рд╡рд┐рд╢реЗрд╖ рд░реВрдк рд╕реЗ, рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рдлрд╝рдВрдХреНрд╢рди рд╣реИрдВ рдЬреЛ рдЕрдиреБрд╡рд╛рдж рдХрд░рддреЗ рд╣реИрдВ (a -> Action) -> Action рдЗрди Cont Action a рдФрд░ рдЗрд╕рдХреЗ рд╡рд┐рдкрд░реАрддред

 cont :: ((a -> Action) -> Action) -> Cont Action a. runCont :: Cont Action a -> (a -> Action) -> Action 

рдЕрдм рд╣рдо MonadIO рдФрд░ MonadConcurrent рдПрдХ рдЙрджрд╛рд╣рд░рдг рдХреЛ рдкрд░рд┐рднрд╛рд╖рд┐рдд рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред

 instance MonadIO Concurrent where liftIO m = Concurrent $ cont $ \c -> Atom $ do a <- m return (ca) 

рджреЗрдЦрддреЗ рд╣реИрдВ рдХрд┐ рдпрд╣рд╛рдВ рдХреНрдпрд╛ рд╣реЛрддрд╛ рд╣реИред
liftIO рдПрдХ IO рдСрдкрд░реЗрд╢рди рдХреЛ рд╕реНрд╡реАрдХрд╛рд░ рдХрд░рддрд╛ рд╣реИ рдФрд░ рдЗрд╕реЗ рдкрд░рдорд╛рдгреБ рдХрд╛рд░реНрд░рд╡рд╛рдИ рдореЗрдВ рд▓рдкреЗрдЯрддрд╛ рд╣реИред рдЕрд░реНрдерд╛рддреН: рд╣рдо cont рдПрдХ рдлрдВрдХреНрд╢рди рдкрд╛рд╕ рдХрд░рддреЗ рд╣реИрдВ рдЬреЛ рдПрдХ рдирд┐рд░рдВрддрд░рддрд╛ рд▓реЗрддрд╛ рд╣реИ (рд╡рд╣ рдпрд╣ рд╣реИ рдХрд┐, c a -> Action рдкреНрд░рдХрд╛рд░ рдХрд╛ a -> Action ) рдФрд░ рдПрдХ рдкрд░рдорд╛рдгреБ рдХреНрд░рд┐рдпрд╛ рдХрд░рддрд╛ рд╣реИ рдЬреЛ IO рдСрдкрд░реЗрд╢рди m ред
рд╣рдордиреЗ Atom рдкрд░рд┐рднрд╛рд╖рд┐рдд рдХрд┐рдпрд╛ рддрд╛рдХрд┐ рдПрдХ рдкрд░рдорд╛рдгреБ рдСрдкрд░реЗрд╢рди рдПрдХ Action рд▓реМрдЯрд╛рдП, рдЬреЛ рдПрдХ рдирд┐рд░рдВрддрд░рддрд╛ рд╣реИред
рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ, рдпрд╣ рд╡рд╣реА рд╣реИ рдЬреЛ рд╣рдо рдХрд░ рд░рд╣реЗ рд╣реИрдВ: рдЬрдм рд╣рдордиреЗ m рдирд┐рд╖реНрдкрд╛рджрд┐рдд рдХрд┐рдпрд╛ рд╣реИ, рддреЛ рд╣рдо c рдХреЙрд▓ рдХрд░рддреЗ рд╣реИрдВ, рдЬреЛ рдЖрд╡рд╢реНрдпрдХ рдирд┐рд░рдВрддрд░рддрд╛ рдХреЛ рд╡рд╛рдкрд╕ рдХрд░рддрд╛ рд╣реИред

рдЕрдм instance MonadConcurrent рдХреЛ рдкрд░рд┐рднрд╛рд╖рд┐рдд рдХрд░реЗрдВ instance MonadConcurrent ред
рдмрд╕ рдкрд░рд┐рднрд╛рд╖рд┐рдд liftIO рдлрд╝рдВрдХреНрд╢рди рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ newCVar рдореЗрдВ рдПрдХ рд▓рд┐рдВрдХ рдмрдирд╛рдПрдВред
takeCVar рдФрд░ putCVar рдЗрд╕реА рдХрд╛рд░реНрд░рд╡рд╛рдИ рдХреЛ рд╡рд╛рдкрд╕ рдХрд░рддреЗ рд╣реИрдВ, рдФрд░ рд╣рдо рдЗрд╕ рд╕рдВрд░рдЪрдирд╛ рдХреЗ рдЕрдВрджрд░ рдЬрд╛рд░реА рд░рдЦрддреЗ рд╣реИрдВред
рдХрд╛рдВрдЯрд╛ рдореЗрдВ, рд╣рдо рдЙрд╕ рдХрд╛рд░реНрд░рд╡рд╛рдИ рдХреЛ рд╡рд╛рдкрд╕ рдХрд░рддреЗ рд╣реИрдВ рдЬрд┐рд╕рдореЗрдВ рджреЛрдиреЛрдВ рдзрд╛рдЧреЗ рд╕рдВрдЧреНрд░рд╣реАрдд рд╣реЛрддреЗ рд╣реИрдВ: рдПрдХ рдХреЛ fork рдлрд╝рдВрдХреНрд╢рди рдХреЗ рддрд░реНрдХреЛрдВ рдореЗрдВ рдкрд╛рд░рд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рджреВрд╕рд░рд╛ рдирд┐рд░рдВрддрд░рддрд╛ рд╕реЗ рдЖрддрд╛ рд╣реИред

 instance MonadConcurrent Concurrent where type CVar Concurrent = MaybeRef newCVar a = liftIO $ liftM MaybeRef $ newIORef (Just a) takeCVar v = Concurrent $ cont (ReadRef v) putCVar va = Concurrent $ cont $ \c -> WriteRef va $ c () fork (Concurrent m) = Concurrent $ cont $ \c -> Fork (runCont m $ \_ -> Stop) $ c () 

рд╣рдорд╛рд░рд╛ рдореЛрдирд╛рдб рд▓рдЧрднрдЧ рддреИрдпрд╛рд░ рд╣реИ, рдпрд╣ рдХреЗрд╡рд▓ рдпрд╣ рд╕реАрдЦрдирд╛ рд╣реИ рдХрд┐ рдЗрд╕реЗ рдХреИрд╕реЗ рд▓реЙрдиреНрдЪ рдХрд┐рдпрд╛ рдЬрд╛рдПред
рд╢реБрд░реБрдЖрдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рд╣рдо рдПрдХ рдлрд╝рдВрдХреНрд╢рди рд▓рд┐рдЦреЗрдВрдЧреЗ рдЬреЛ Action рд▓реЙрдиреНрдЪ рдХрд░реЗрдЧрд╛ред рдпрд╣ рдХреНрд░рд┐рдпрд╛рдУрдВ рдХреА рдПрдХ рд╕реВрдЪреА рд▓реЗрддрд╛ рд╣реИ, рдкреНрд░рддреНрдпреЗрдХ рддрддреНрд╡ рдЬрд┐рд╕рдореЗрдВ рдПрдХ рдЕрд▓рдЧ рдзрд╛рдЧрд╛ рд╣реЛрддрд╛ рд╣реИред
рдХрд╛рд░реНрд░рд╡рд╛рдИ рд╢реБрд░реВ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рд░рдгрдиреАрддрд┐рдпрд╛рдБ рдЕрд▓рдЧ рд╣реЛ рд╕рдХрддреА рд╣реИрдВред рд╣рдо рджреЛ рдмрд┐рдВрджреБрдУрдВ рдкрд░ рдирд┐рд░реНрдгрдп рд▓реЗрдВрдЧреЗ: рдереНрд░реЗрдбреНрд╕ рдХреЛ рдирд┐рд╖реНрдкрд╛рджрд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдХрд┐рд╕ рдХреНрд░рдо рдореЗрдВ, рдФрд░ рдпрджрд┐ рд╣рдо рдХрд┐рд╕реА рд╡реИрд░рд┐рдПрдмрд▓ рд╕реЗ рдорд╛рди рдХреЛ рдЦрд╛рд▓реА рдХрд░рдиреЗ рдХрд╛ рдкреНрд░рдпрд╛рд╕ рдХрд░рддреЗ рд╣реИрдВ рддреЛ рдХреНрдпрд╛ рдХрд░реЗрдВред рдЖрдкрдХреЛ рдпрд╛рдж рджрд┐рд▓рд╛ рджреВрдВ рдХрд┐ рдЪрд░ рдореЗрдВ рдХреБрдЫ рднреА рдирд╣реАрдВ рд╣реЛ рд╕рдХрддрд╛ рд╣реИ, рдФрд░ рдлрд┐рд░ рд╣рдореЗрдВ рджреВрд╕рд░реЗ рдзрд╛рдЧреЗ рдХреЗ рд▓рд┐рдП рдХреБрдЫ рдХрд░рдиреЗ рдХреА рдкреНрд░рддреАрдХреНрд╖рд╛ рдХрд░рдиреА рд╣реЛрдЧреАред
рдЪрд▓реЛ рдкрд╣рд▓реЗ рдПрдХ рд╕рд░рд▓ рд╕рдВрд╕реНрдХрд░рдг рд▓рд┐рдЦрддреЗ рд╣реИрдВ рдЬрд╣рд╛рдВ рд╣рдо рдмрджрд▓реЗ рдореЗрдВ рдзрд╛рдЧреЗ рдирд┐рд╖реНрдкрд╛рджрд┐рдд рдХрд░реЗрдВрдЧреЗ; рдФрд░ рдПрдХ рдЦрд╛рд▓реА рдЪрд░ рд╕реЗ рдкрдврд╝рдиреЗ рдХреА рдХреЛрд╢рд┐рд╢ рдХрд░ рд░рд╣реЗ рдзрд╛рдЧреЗ рдХреЛ рдХрддрд╛рд░ рдХреЗ рдЕрдВрдд рдореЗрдВ рд▓реЗ рдЬрд╛рдпрд╛ рдЬрд╛рдПрдЧрд╛ред

 runAction :: [Action] -> IO () --    , . runAction [] = return () --   ,  ,   ,    . runAction (Atom m : as) = do a' <- m runAction $ as ++ [a'] --       . runAction (Fork a1 a2 : as) = runAction $ as ++ [a1,a2] --    . runAction (Stop : as) = runAction as runAction (ReadRef (MaybeRef ref) c : as) = do --   . ma <- readIORef ref case ma of --    -,  Just a -> do --   . writeIORef ref Nothing --     . runAction (as ++ [ca]) --     ,       ,         . Nothing -> runAction (as ++ [ReadRef (MaybeRef ref) c]) --    ,     . runAction (WriteRef (MaybeRef ref) val a : as) = do writeIORef ref (Just val) runAction (as ++ [a]) 

рдзреНрдпрд╛рди рджреЗрдВ рдХрд┐ putMVar рд╣рдорд╛рд░реЗ WriteRef рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдХреА рддреБрд▓рдирд╛ рдореЗрдВ рдереЛрдбрд╝рд╛ рдЕрд▓рдЧ рдХрд╛рдо рдХрд░рддрд╛ рд╣реИред
рдпрджрд┐ рд▓рд┐рдВрдХ рдореЗрдВ рдкрд╣рд▓реЗ рд╕реЗ рд╣реА рдХреБрдЫ рдореВрд▓реНрдп рдерд╛, рддреЛ putMVar рдзрд╛рдЧреЗ рдХреЛ рддрдм рддрдХ рдлреНрд░реАрдЬ putMVar рдЬрдм рддрдХ рдХрд┐ рдЪрд░ рдХреЛ рдореБрдХреНрдд рдирд╣реАрдВ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред рдЗрд╕ рд╕реНрдерд┐рддрд┐ рдореЗрдВ, рдорд╛рди рдХреЛ рдкреБрди: рд▓рд┐рдЦреЗрдВред
рдпрд╣ рдПрдХ рд╕рдВрд╕реНрдХрд░рдг рдмрдирд╛рдиреЗ рдХреЗ рд▓рд╛рдпрдХ рдирд╣реАрдВ рд╣реИ рдЬреЛ рдЗрд╕ рд╕реНрдерд┐рддрд┐ рдореЗрдВ putMVar рд░реВрдк рдореЗрдВ рдХрд╛рдо рдХрд░рддрд╛ рд╣реИ, рддрд╛рдХрд┐ рдХреЛрдб рдХреЛ putMVar рди рдХрд░реЗрдВред

рдЕрдЧрд▓рд╛, рдПрдХ рдлрд╝рдВрдХреНрд╢рди рд▓рд┐рдЦреЗрдВ рдЬреЛ Concurrent , рдФрд░ main рдлрд┐рд░ рд╕реЗ рдкрд░рд┐рднрд╛рд╖рд┐рдд рдХрд░рддрд╛ рд╣реИред

 runConcurrent :: Concurrent () -> IO () runConcurrent (Concurrent c) = runAction [runCont c $ \_ -> Stop] main = runConcurrent (runPhil 5) 

рдЪреВрдВрдХрд┐ рдЕрдм рд╣рдо рдПрдХ рд╣реА рдереНрд░реЗрдб рдореЗрдВ рдХрд╛рдо рдХрд░ рд░рд╣реЗ рд╣реИрдВ, рдФрд░ threadDelay рд╕рднреА рдХрд╛рдо рдХрд░рдирд╛ рдмрдВрдж рдХрд░ рджреЗрддрд╛ рд╣реИ, рдЧрддрд┐ рдереЛрдбрд╝реА рдХрдо рд╣реЛ рдЧрдИ рд╣реИред

рд▓реЗрдЦрди рдкрд░реАрдХреНрд╖рдг


рд╕рдордп рдЖ рдЧрдпрд╛ рд╣реИ рдХрд┐ "рдкрдХрд╡рд╛рди рдХреЗ рд▓рд┐рдП рдорд╕рд╛рд▓рд╛ рдЬреЛрдбрд╝реЗрдВ" - рд╣рдорд╛рд░реЗ рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП рдкрд░реАрдХреНрд╖рдг рд▓рд┐рдЦреЗрдВред
рдРрд╕рд╛ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рд╣рдо QuickCheck рд▓рд╛рдЗрдмреНрд░реЗрд░реА рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реИрдВ, рдЬреЛ рдкрд░реАрдХреНрд╖рдгреЛрдВ рдХреЗ рд▓рд┐рдП рдпрд╛рджреГрдЪреНрдЫрд┐рдХ рдЗрдирдкреБрдЯ рдЙрддреНрдкрдиреНрди рдХрд░рддрд╛ рд╣реИред рдЪреВрдВрдХрд┐ рд╣рдо рдЕрдкрдиреЗ рдереНрд░реЗрдб рдХреЛ рдЕрд▓рдЧ-рдЕрд▓рдЧ рдХреНрд░рдо рдореЗрдВ рдЪрд▓рд╛рдирд╛ рдЪрд╛рд╣рддреЗ рд╣реИрдВ, рд╣рдорд╛рд░реЗ рдкрд░реАрдХреНрд╖рдгреЛрдВ рдХрд╛ рдЗрдирдкреБрдЯ рд╡рд╣ рдХреНрд░рдо рд╣реИ рдЬрд┐рд╕рдореЗрдВ рд╣рдо рд╕реВрдЪреА рд╕реЗ рдЕрдЧрд▓реЗ рдереНрд░реЗрдб рдХрд╛ рдЪрдпрди рдХрд░рддреЗ рд╣реИрдВред
рдЗрдирдкреБрдЯ рдХреЛ рд╕рдВрдЦреНрдпрд╛рдУрдВ рдХреА рд╕реВрдЪреА рдХреЗ рд╕рд╛рде рдПрдирдХреЛрдб рдХрд░рдирд╛ рд╕рдВрднрд╡ рд╣реИ, рд▓реЗрдХрд┐рди рд╕рдорд╕реНрдпрд╛ рдпрд╣ рд╣реИ рдХрд┐ рд╣рдо рдкрд╣рд▓реЗ рд╕реЗ рдирд╣реАрдВ рдЬрд╛рдирддреЗ рд╣реИрдВ рдХрд┐ рдЗрди рдирдВрдмрд░реЛрдВ рдХреЛ рдХрд┐рд╕ рд╕реАрдорд╛ рд╕реЗ рдЪреБрдирд╛ рдЬрд╛рдирд╛ рдЪрд╛рд╣рд┐рдП, рдХреНрдпреЛрдВрдХрд┐ рдереНрд░реЗрдбреНрд╕ рдХреА рд╕рдВрдЦреНрдпрд╛ рднрд┐рдиреНрди рд╣реЛ рд╕рдХрддреА рд╣реИред
рдЗрд╕рд▓рд┐рдП, рд╣рдо рдЗрдирдкреБрдЯ рдбреЗрдЯрд╛ рдХреЛ Int -> Int рдХреЗ рдкреНрд░рдХрд╛рд░реЛрдВ рдХреА рдПрдХ рд╕реВрдЪреА рдХреЗ рд╕рд╛рде рдПрдиреНрдХреЛрдб рдХрд░реЗрдВрдЧреЗ, рдЬреЛ рдирдВрдмрд░ n рд▓реЗрддреЗ рд╣реИрдВ рдФрд░ рдЕрдВрддрд░рд╛рд▓ рд╕реЗ рдПрдХ рдирдВрдмрд░ рд▓реМрдЯрд╛рддреЗ рд╣реИрдВ [0,n-1] ред

 newtype Route = Route [Int -> Int] 

QuickCheck рд▓рд╛рдЗрдмреНрд░реЗрд░реА рджреНрд╡рд╛рд░рд╛ рдкреНрд░рджрд╛рди рдХреА рдЬрд╛рдиреЗ рд╡рд╛рд▓реА Arbitrary рдХреНрд▓рд╛рд╕ рдХрд╛ рдЙрджреНрджреЗрд╢реНрдп рдЙрди рдкреНрд░рдХрд╛рд░реЛрдВ рдХрд╛ рд╡рд░реНрдгрди рдХрд░рдирд╛ рд╣реИ рдЬреЛ рдпрд╛рджреГрдЪреНрдЫрд┐рдХ рддрддреНрд╡реЛрдВ рдХреЛ рдЙрддреНрдкрдиреНрди рдХрд░рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддреЗ рд╣реИрдВред
рдЗрд╕ рд╡рд░реНрдЧ рдореЗрдВ рджреЛ рдХрд╛рд░реНрдп рдмрддрд╛рдП рдЧрдП рд╣реИрдВ - shrink рдФрд░ arbitrary ред
shrink рдХрд╛ рдбрд┐рдлрд╝реЙрд▓реНрдЯ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рд╣реИ, рдЗрд╕рд▓рд┐рдП рд╣рдордиреЗ рдЗрд╕реЗ рдлрд┐рд░ рд╕реЗ рдкрд░рд┐рднрд╛рд╖рд┐рдд рдирд╣реАрдВ рдХрд┐рдпрд╛ рд╣реИред
arbitrary рдХрд╛рд░реНрдп рдореЗрдВ, рд╣рдо рдпрд╛рджреГрдЪреНрдЫрд┐рдХ рдХрд╛рд░реНрдпреЛрдВ рдХреА рдПрдХ рд╕реВрдЪреА рддреИрдпрд╛рд░ рдХрд░рддреЗ рд╣реИрдВ, рдЬрд╣рд╛рдБ рдкреНрд░рддреНрдпреЗрдХ рдлрд╝рдВрдХреНрд╢рди рдЕрдВрддрд░рд╛рд▓ рд╕реЗ рдПрдХ рдирдВрдмрд░ рджреЗрддрд╛ рд╣реИ [0,n-1] ред

 instance Arbitrary Route where arbitrary = fmap Route (listOf arbitraryFun) where arbitraryFun = MkGen $ \qsn -> unGen (choose (0, n - 1)) qs 

рд╣рдо Route рд▓рд┐рдП instance Show рдХреЛ рднреА рдкрд░рд┐рднрд╛рд╖рд┐рдд рдХрд░рддреЗ рд╣реИрдВ, рдХреНрдпреЛрдВрдХрд┐ QuickCheck рдХреЛ QuickCheck рдЖрд╡рд╢реНрдпрдХрддрд╛ QuickCheck ред
рджреБрд░реНрднрд╛рдЧреНрдп рд╕реЗ, рд╣рдо рдПрдХ show рднреА рдЙрдкрдпреЛрдЧреА рдирд╣реАрдВ рд▓рд┐рдЦ рд╕рдХрддреЗ show ред рдЗрд╕рдХреЗ рдЕрд▓рд╛рд╡рд╛, рдЗрд╕ рдлрд╝рдВрдХреНрд╢рди рдХрд╛ рдЙрдкрдпреЛрдЧ рдирд╣реАрдВ рдХрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛, рдЗрд╕рд▓рд┐рдП рд╣рдо рдЗрд╕реЗ рдЕрдкрд░рд┐рднрд╛рд╖рд┐рдд рдЫреЛрдбрд╝ рджреЗрддреЗ рд╣реИрдВред

 instance Show Route where show = undefined 

рдЕрдм рдЖрдк runAction рдХрд╛ рдПрдХ рд╕реНрдорд╛рд░реНрдЯ рд╕рдВрд╕реНрдХрд░рдг рд▓рд┐рдЦрдирд╛ рд╢реБрд░реВ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред
рдкрд╣рд▓рд╛ рдЕрдВрддрд░ рдпрд╣ рд╣реИ рдХрд┐ рд╣рдо рдкрд░рдорд╛рдгреБ рдХрд╛рд░реНрдпреЛрдВ рдХреЗ рдирд┐рд╖реНрдкрд╛рджрди рдФрд░ рд▓рд┐рдВрдХ рдХреЗ рд╕рд╛рде рдХрд╛рдо рдХреЛ рдЕрд▓рдЧ рдХрд░рддреЗ рд╣реИрдВред
рд╢реБрд░реВ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рд╣рдо рдПрдХ рд╕рд╣рд╛рдпрдХ рдлрд╝рдВрдХреНрд╢рди skipAtoms рдЬреЛ рдкрд░рдорд╛рдгреБ рдХреНрд░рд┐рдпрд╛рдПрдВ рдХрд░рддрд╛ рд╣реИ: рдлрд╝рдВрдХреНрд╢рди рдХреНрд░рд┐рдпрд╛рдУрдВ рдХреА рдПрдХ рд╕реВрдЪреА рдХреЛ рд╕реНрд╡реАрдХрд╛рд░ рдХрд░рддрд╛ рд╣реИ, Atom , Fork рдФрд░ Stop , рдФрд░ рдкрд░рд┐рдгрд╛рдорд╕реНрд╡рд░реВрдк рдПрдХ рдкрд░рд┐рдгрд╛рдо рджреЗрддрд╛ рд╣реИред

 skipAtoms :: [Action] -> IO [Action] skipAtoms [] = return [] skipAtoms (Atom m : as) = do a <- m skipAtoms (as ++ [a]) skipAtoms (Fork a1 a2 : as) = skipAtoms (as ++ [a1,a2]) skipAtoms (Stop : as) = skipAtoms as skipAtoms (a : as) = fmap (a:) (skipAtoms as) 

runAction рдХреЗ рдирдП рд╕рдВрд╕реНрдХрд░рдг рдФрд░ рдкрд┐рдЫрд▓реЗ рдПрдХ рдХреЗ рдмреАрдЪ рджреВрд╕рд░рд╛ рдЕрдВрддрд░ рдпрд╣ рд╣реИ рдХрд┐ рд╣рдо рдЧрддрд┐рд░реЛрдз рдХреА рдкреНрд░рд╛рдкреНрддрд┐ рдХреЛ рдЯреНрд░реИрдХ рдХрд░рддреЗ рд╣реИрдВред
рдРрд╕рд╛ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рдХреНрд░рд┐рдпрд╛рдУрдВ рдХреА рджреЛ рд╕реВрдЪрд┐рдпрд╛рдБ рдкреНрд░рд╛рд░рдВрдн рдХрд░реЗрдВред рдкрд╣рд▓реЗ рднрдВрдбрд╛рд░ рд╕рдХреНрд░рд┐рдп (рд╣рдорд╛рд░реЗ рджреНрд╡рд╛рд░рд╛ рдирд┐рд╖реНрдкрд╛рджрд┐рдд) рдзрд╛рдЧреЗред рджреВрд╕рд░реЗ рдореЗрдВ, рдХрд┐рд╕реА рднреА рд▓рд┐рдВрдХ рдХреЛ рдЕрдкрдбреЗрдЯ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдереНрд░реЗрдб рдЗрдВрддрдЬрд╛рд░ рдХрд░ рд░рд╣реЗ рд╣реИрдВред
рдпрджрд┐ рд╕рдХреНрд░рд┐рдп рдереНрд░реЗрдбреНрд╕ рдХреА рд╕реВрдЪреА рд░рд┐рдХреНрдд рд╣реИ, рд▓реЗрдХрд┐рди рдХреЛрдИ рдкреНрд░рддреАрдХреНрд╖рд╛ рд╕реВрдЪреА рдирд╣реАрдВ рд╣реИ, рддреЛ рд╣рдореЗрдВ рдПрдХ рдЧрддрд┐рд░реЛрдз рдорд┐рд▓рд╛, рдФрд░ рдЗрд╕ рдорд╛рдорд▓реЗ рдореЗрдВ рд╣рдо рдПрдХ рдЕрдкрд╡рд╛рдж рдлреЗрдВрдХрддреЗ рд╣реИрдВред

рддреАрд╕рд░рд╛ рдирд╡рд╛рдЪрд╛рд░ Route рдирдВрдмрд░ рдХрд╛ рдПрдХ рддрд░реНрдХ рд╣реИ рдЬрд┐рд╕рдХрд╛ рдЙрдкрдпреЛрдЧ рдзрд╛рд░рд╛ рд╕рдВрдЦреНрдпрд╛ рдХреЛ рдЪреБрдирдиреЗ рдХреЗ рд▓рд┐рдП рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ рдЬрд┐рд╕реЗ рд╡рд░реНрддрдорд╛рди рдЪрд░рдг рдореЗрдВ рдХрд┐рдпрд╛ рдЬрд╛рдирд╛ рдЪрд╛рд╣рд┐рдПред

 runAction :: Route -> [Action] -> [Action] -> IO () runAction _ [] [] = return () runAction _ [] _ = fail "Deadlock" runAction (Route []) _ _ = return () runAction (Route (r:rs)) as bs = do as <- skipAtoms as let n = length as case splitAt (rn) as of (as1, ReadRef (MaybeRef ref) c : as2) -> do ma <- readIORef ref case ma of Just a -> do writeIORef ref Nothing runAction (Route rs) (as1 ++ [ca] ++ as2) bs Nothing -> runAction (Route rs) (as1 ++ as2) (bs ++ [ReadRef (MaybeRef ref) c]) (as1, WriteRef (MaybeRef ref) xc : as2) -> do writeIORef ref (Just x) runAction (Route rs) (as1 ++ [c] ++ as2 ++ bs) [] 

runConcurrent рдлрд╝рдВрдХреНрд╢рди рдмрд╣реБрдд рдЕрдзрд┐рдХ рдирд╣реАрдВ рдмрджрд▓рд╛ рдЧрдпрд╛ рд╣реИред

 runConcurrent :: Route -> Concurrent () -> IO () runConcurrent r (Concurrent c) = runAction r [runCont c $ \_ -> Stop] [] 

рдЖрдк рдкрд╣рд▓реЗ рддрд░реНрдХ рдХреЗ рд░реВрдк рдореЗрдВ round_robin рдкрд╛рд╕ рдХрд░рдХреЗ рдпрд╣ рдЬрд╛рдВрдЪ рд╕рдХрддреЗ рд╣реИрдВ рдХрд┐ рдирдпрд╛ рд╕рдВрд╕реНрдХрд░рдг рдХреИрд╕реЗ рдХрд╛рдо рдХрд░рддрд╛ рд╣реИред рдпрд╣ рдПрдХ рд╕рд╛рдзрд╛рд░рдг рдирд┐рд╖реНрдкрд╛рджрди рд░рдгрдиреАрддрд┐ рд╣реИ, рдЬреЛ runAction рдлрд╝рдВрдХреНрд╢рди рд╕реЗ рдкрд╣рд▓реЗ рдХрд╛рдо рдХрд░рддрд╛ рд╣реИред рдпрд╣рд╛рдВ рд╣рдо рдмрд╕ рдПрдХ рдЕрдирдВрдд рд╕реВрдЪреА рдмрдирд╛рддреЗ рд╣реИрдВ рдФрд░ рдкреНрд░рддреНрдпреЗрдХ рддрддреНрд╡ рдХреЗ рд▓рд┐рдП рд╣рдо рд╢реЗрд╖ рдореЙрдбреБрд▓реЛ рдХреЛ рдереНрд░реЗрдбреНрд╕ рдХреА рд╕рдВрдЦреНрдпрд╛ рд▓реЗрддреЗ рд╣реИрдВред

 round_robin :: Route round_robin = Route $ map rem [0..] 

рдЗрд╕ рдЗрдирдкреБрдЯ рдкрд░ рдЧрдгрдирд╛рдУрдВ рдХреЛ рдЪрд▓рд╛рдиреЗ рд╕реЗ, рд╣рдореЗрдВ рдЬрд▓реНрджреА рд╕реЗ рдЧрддрд┐рд░реЛрдз рдкреНрд░рд╛рдкреНрдд рд╣реЛрдиреЗ рдХреА рд╕рдВрднрд╛рд╡рдирд╛ рд╣реИ - рдЗрд╕ рддрдереНрдп рдХреЗ рдХрд╛рд░рдг рдХрд┐ рд╣рдорд╛рд░реЗ рдЙрджрд╛рд╣рд░рдг рдХрд╛ рдХрд╛рдо рдпрд╛рджреГрдЪреНрдЫрд┐рдХ рд╕рдВрдЦреНрдпрд╛ рдЬрдирд░реЗрдЯрд░ рдкрд░ рдЖрдзрд╛рд░рд┐рдд рд╣реИ - рдЗрд╕рд▓рд┐рдП, рдЗрд╕ рддрдереНрдп рдХреЗ рдмрд╛рд╡рдЬреВрдж рдХрд┐ рдЗрдирдкреБрдЯ рд╣рдореЗрд╢рд╛ рд╕рдорд╛рди рд╣реЛрддрд╛ рд╣реИ, рдирд┐рд╖реНрдкрд╛рджрди рдЖрджреЗрд╢ рдирд┐рдХрд▓рддрд╛ рд╣реИ рдмреЗрддрд░рддреАрдм рдврдВрдЧ рд╕реЗред
рдпрджрд┐ рд╣рдорд╛рд░реЗ рдЙрджрд╛рд╣рд░рдг рдЕрдзрд┐рдХ рдирд┐рд░реНрдзрд╛рд░рдХ рдереЗ, рддреЛ рд╣рдореЗрдВ рдЗрдирдкреБрдЯ рдбреЗрдЯрд╛ рдХреЛ рдпрд╛рджреГрдЪреНрдЫрд┐рдХ рд░реВрдк рд╕реЗ рдЕрд▓рдЧ рдХрд░рдирд╛ рд╣реЛрдЧрд╛, рдЬреЛ рдЕрдм рд╣рдо рдХрд░реЗрдВрдЧреЗред

 main = quickCheck $ monadicIO $ do r <- pick arbitrary run $ runConcurrent r (runPhil 5) 

рд╣рдо рдкреВрд░реНрд╡ рдореЗрдВ рд▓рд╛рдЧреВ рдХрд┐рдП рдЧрдП arbitrary рдлрд╝рдВрдХреНрд╢рди рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ Route рдкреНрд░рдХрд╛рд░ рдХрд╛ рдПрдХ рдордирдорд╛рдирд╛ рддрддреНрд╡ рдЪреБрдирддреЗ рд╣реИрдВред рдлрд┐рд░ рд╣рдо рдЗрд╕ рдЗрдирдкреБрдЯ рдкрд░ рдЕрдкрдиреА рдЧрдгрдирд╛ рд╢реБрд░реВ рдХрд░рддреЗ рд╣реИрдВред
QuickCheck рдХрд╛ рдзреНрдпрд╛рди рд░рдЦреЗрдЧрд╛, рдЕрд░реНрдерд╛рддреН: рдпрд╣ рд╣рдорд╛рд░реЗ рдкрд░реАрдХреНрд╖рдг рдХреЛ 100 рдмрд╛рд░ рдЪрд▓рд╛рдПрдЧрд╛, рд╣рд░ рдмрд╛рд░ рдЗрдирдкреБрдЯ рдбреЗрдЯрд╛ рдХреЗ рдЖрдХрд╛рд░ рдХреЛ рдмрдврд╝рд╛рдПрдЧрд╛ред

рдХрд╛рд░реНрдпрдХреНрд░рдо рдХреЛ рдЪрд▓рд╛рдиреЗ рдкрд░, рд╣рдо рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рджреЗрдЦреЗрдВрдЧреЗ:

 ... 3 took left fork 4 put forks 4 is awaiting 5 took left fork 4 took left fork 1 took right fork 1 put forks 1 is awaiting 1 took left fork 2 took left fork *** Failed! Exception: 'user error (Deadlock)' (after 36 tests): 

рдХреНрдпрд╛ рдкрд╛рдирд╛ рдЬрд░реВрд░реА рдерд╛!

рдирд┐рд╖реНрдХрд░реНрд╖


рд╣рдордиреЗ рдЙрди рдкрд░реАрдХреНрд╖рдгреЛрдВ рдХреЛ рд▓рд┐рдЦрдирд╛ рд╕реАрдЦрд╛ рдЬреЛ рдПрдХ рдмрд╣реБ-рдереНрд░реЗрдбреЗрдб рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдореЗрдВ рдЧрддрд┐рд░реЛрдз рдХреА рд╕реНрдерд┐рддрд┐ рдХрд╛ рдкрддрд╛ рд▓рдЧрд╛ рд╕рдХрддреЗ рд╣реИрдВред
рдЗрд╕ рдкреНрд░рдХреНрд░рд┐рдпрд╛ рдореЗрдВ, рд╣рдордиреЗ Cont рдореЛрдирдб, рдЯрд╛рдЗрдк рдкрд░рд┐рд╡рд╛рд░реЛрдВ, рдЕрд╕реНрддрд┐рддреНрд╡рдЧрдд рдорд╛рддреНрд░рд╛ рдХрд╛ рдЙрдкрдпреЛрдЧ рдФрд░ QuickCheck рд▓рд╛рдЗрдмреНрд░реЗрд░реА рдХреЗ рдЙрджрд╛рд╣рд░рдгреЛрдВ рдХреЛ рджреЗрдЦрд╛ред
рдЗрд╕рдХреЗ рдЕрд▓рд╛рд╡рд╛, рд╣рдордиреЗ рд╕реАрдЦрд╛ рдХрд┐ рдХреИрд╕реЗ рдХрд╛рдордЪрд▓рд╛рдК рд╕рд╛рдордЧреНрд░реА рд╕реЗ рдмрд╣реБ-рдереНрд░реЗрдбреЗрдб рдкреНрд░реЛрдЧреНрд░рд╛рдо рдирд┐рд╖реНрдкрд╛рджрди рдХреЗ рдПрдХ рдореЙрдбрд▓ рдХреЛ рдЗрдХрдЯреНрдард╛ рдХрд░рдирд╛ рд╣реИред

Source: https://habr.com/ru/post/In224075/


All Articles