コラッツ予想がとけたらいいな2

自分の考察を書いていきます。

デバッグ実行するプログラム

前回のデバッグ実行するプログラムを改良してみた。
キー入力と実行関数の再帰部分をモジュール化した。
これでメインルーチンはすっきりした。

module DebugRun where

import Control.Concurrent
import System.IO.Unsafe

data St = Run | Debug | Wait deriving (Eq)

-- like global value
st = unsafePerformIO $ newMVar Run

putMVarForce :: MVar a -> a -> IO ()
putMVarForce mv d = do
  emp <- isEmptyMVar mv
  if emp == True then putMVar mv d
  else takeMVar mv >>= \_ -> putMVar mv d

waitloop :: IO () -> IO ()
waitloop iofunc = do
  st2 <- readMVar st
  if st2 == Run then iofunc
  else do
    putMVarForce st Wait
    waitloop' iofunc
      where
        waitloop' :: IO () -> IO ()
        waitloop' iofunc = do
          st2 <- readMVar st
          if st2 == Wait then waitloop' iofunc
          else iofunc

keyloop :: ThreadId -> IO ()
keyloop ou = do
  k <- getChar
  case k of
    'r' -> putMVarForce st Run
    'd' -> putMVarForce st Debug
    _   -> return ()
  if k == 'q' then killThread ou
  else keyloop ou
module Keyin2 where

import Control.Concurrent
import DebugRun

outgo :: String -> IO ()
outgo [] = do { print ""; putStrLn "thread end."; }
outgo (x:xs) = do
  print (x:xs)
  threadDelay (1*1000*1000)
  waitloop $ outgo xs

main = do
  ou <- forkIO $ outgo "asdfghjklqwerty"
  keyloop ou
  putStrLn "main end."

・実行関数が終わったときに、外からgetCharを止める方法がどうしても思いつかなかった。
・禁断のunsafePerformIOに手を染めてしまった。