简体   繁体   中英

Haskell: Thread and IO type

I am studying the Haskell to the thread part. I try to create 2 threads to do the different calculation. This is a really simple function just for practice. The code like this:

import Control.Concurrent (forkIO)

task4 a b = do
    forkIO $ a^b
    forkIO $ b^a


    if (a^b) > (b^a) then putStrLn ([a] ++ "^"++[b] ++ "=" ++ [a^b] ++ "is bigger!")
                    else putStrLn ([b] ++ "^"++[a] ++ "=" ++ [b^a] ++ "is bigger!") 

I don't know how to dual with the type inside the do block. And am I right to create threads like this?

Since some time has passed, here's how you would do it with threads:

-- helper function for all other methods
message a b = (show a) ++ " ? " ++ (show b) ++ " " ++ (show . compare a $ b)

threads a b = do
  abVar <- newEmptyMVar
  baVar <- newEmptyMVar
  forkIO $ putMVar abVar (a^b)
  forkIO $ putMVar baVar (b^a)
  ab <- takeMVar abVar
  ba <- takeMVar baVar
  putStrLn $ message ab ba

That's a mouthful. Even worse, it's not pure anymore. After all, your program is basically nothing more than

simple a b = message (a^b) (b^a)

-- IO version
simpleIO :: Integer -> Integer -> IO ()
simpleIO a b = putStrLn $ simple a b

Or at least it should behave the same. If you want to do this in parallel, there's no need for IO , using par and pseq :

parAB a b = force ab `par` force ba `pseq` message ab ba
  where ab = a^b
        ba = b^a

-- IO version    
parABIO a b = putStrLn $ parAB a b

But in the end, using parallel or concurrent techniques on such simple tasks as a^b won't gain you anything:

par is generally used when the value of a is likely to be required later, but not immediately. Also it is a good idea to ensure that a is not a trivial computation, otherwise the cost of spawning it in parallel overshadows the benefits obtained by running it in parallel.

This can be checked by using Criterion:

import Control.Concurrent
import Control.Parallel
import Control.DeepSeq
import Criterion.Main

message a b = (show a) ++ " ? " ++ (show b) ++ " " ++ (show . compare a $ b)

simple, parAB :: Integer -> Integer -> String
simpleIO, parABIO, threads :: Integer -> Integer -> IO ()

simple a b = message (a^b) (b^a)

simpleIO a b = putStrLn $ simple a b

parAB a b = force ab `par` force ba `pseq` message ab ba
  where ab = a^b
        ba = b^a

parABIO a b = putStrLn $ parAB a b 

threads a b = do
  abVar <- newEmptyMVar
  baVar <- newEmptyMVar
  forkIO $ putMVar abVar (a^b)
  forkIO $ putMVar baVar (b^a)
  ab <- takeMVar abVar
  ba <- takeMVar baVar
  putStrLn $ message ab ba

main = defaultMain [
  bgroup "simpleIO" 
    [ bench "1531235 123152123" $ whnf (simpleIO 1531235) 123152123
    , bench "2 121351356" $ whnf (simpleIO 2) 121351356
    , bench "12346 415" $ whnf (simpleIO 12346) 415
    ],
  bgroup "parABIO" 
    [ bench "1531235 123152123" $ whnf (parABIO 1531235) 123152123
    , bench "2 121351356" $ whnf (parABIO 2) 121351356
    , bench "12346 415" $ whnf (parABIO 12346) 415
    ],
  bgroup "threads" 
    [ bench "1531235 123152123" $ whnf (threads 1531235) 123152123
    , bench "2 121351356" $ whnf (threads 2) 121351356
    , bench "12346 415" $ whnf (threads 12346) 415
    ]
  ]

Further resources

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM