Haskellにおける遅延評価でモナドが計算順序を定めることの意味が ようやくにして理解できた. つまり、いくら関数をつないでも渡した引数は必要になるまで評価 してくれない.それが入出力であっても.
import System.IO.Unsafe
getLn :: () -> String
getLn _ = unsafePerformIO getLine
int :: String -> Int
int = unsafePerformIO.readIO
getInt :: () -> Int
getInt () = int$getLn ()
double :: String -> Double
double = unsafePerformIO.readIO
getDouble :: () -> Double
getDouble () = double$getLn ()unsafePerformIO :: IO a -> a である.なんて便利なんだ!プロコンでHaskellを使う時の為の テンプレートのつもりで上を書いた. getLn、getDouble は何かしら引数を渡さないといけない関数に するので毎回入力をとる. 初め
getDouble = double $ getLineとしていたから、getDoubleを複数回呼び出しても一行しか入力を 受け取ってくれなかった.
使ってみよう.
main =
    let x = getInt ()
        y = getInt () in
        print (x + y)便利だ!
main =
    let x = getDouble ()
        a = getInt () in
        print (x ^ a)たぶんパースエラーを起こす.私のGHCiは、(^)の演算にまず右側を 評価するらしいので、まず getInt を呼び出すらしいのだ. コードを見るとつい x を先に評価してるように思えてしまう.
遅延評価がデフォルトであることの意味がやっと分かった
じゃあどう書くかって言われて、こんなコードくらいしか書けないよ
main = do
    s <- getLine
    x <- readIO s :: IO Double
    t <- getLine
    a <- readIO t :: IO Int
    print (x^a)do記法使っときながら (>>=) も使うなら
main = do
    x <- getLine >>= readIO :: IO Double
    a <- getLine >>= readIO :: IO Int
    b <- getLine >>= readIO :: IO Int
    print (x^(a+b))なんかApplicativeとかに<$>だとかでまともに書けるのあった ようなのをなんとなく覚えてる.
ていうか、長いし、
(define-macro (getInt a)
    a <- getLine >>= readIO :: Int)とか書きたくなる