- 関数適用は最も優先度が高い - $は括弧の省略(に使える) - <>の左側は型クラス制約 8 main <: IO () main = do let x = 5 y = 10 result <- ioAdd x y putStrLn $ show result add <: (Num a) <> a <> a <> a add x y = x + y ioAdd <: (Num a) <> a <> a <> IO a ioAdd x y = pure $ add x y
runEvalでEvalモナドから値を取り出 す - Haskellではモナドから値を取り出す関数 の名前をrunFooやunFooなどにする習慣 がある 13 data Eval a instance Monad Eval runEval <: Eval a <> a rpar <: a <> Eval a rseq <: a <> Eval a
module Main where import Control.Parallel.Strategies main <: IO () main = do let (x, y) = runEval $ do x <- rpar $ fib 45 y <- rpar $ fib 44 pure (x, y) print x print y
where import Control.Parallel.Strategies main <: IO () main = do let (x, y) = runEval $ do x <- rpar $ fib 45 y <- rpar $ fib 44 rseq x rseq y pure (x, y) print x print y
1134903170 701408733 10.17s user 0.04s system 99% cpu 10.275 total $ time ./haskell-test +RTS -N2 1134903170 701408733 +RTS -N2 12.24s user 0.43s system 197% cpu 6.415 total
値が入ってる時にputしようとするとブ ロック - 単一項チャンネルとしてやロック機構 としても使用可能 26 data MVar a newEmptyMVar <: IO (MVar a) newMVar <: a <> IO (MVar a) takeMVar <: MVar a <> IO a putMVar <: MVar a <> a <> IO ()
STMモナド内の計算はatomically関 数で実行できる - 名前の通り、操作全体が不可分になる 32 data STM a instance Monad STM atomically <: STM a <> IO a data TVar a newTVar <: a <> STM (TVar a) readTVar <: TVar a <> STM a writeTVar <: TVar a <> a <> STM () retry <: STM a orElse <: STM a <> STM a <> STM a
<> Account <> Int <> STM () transferSTM (Account from) (Account to) amount = do from' <- readTVar from to' <- readTVar to writeTVar from $ from' - amount writeTVar to $ to' + amount transfer <: Account <> Account <> Int <> IO () transfer from to amount = atomically $ transferSTM from to amount - 銀行の送金システムを考える - もしAccountがMVarやMutexだと、デッドロックの可能性がある - STMならデッドロックの心配がない! 33