2016-08-28 5 views
0

I/think/IOモナドを含むdoブロックで変数割当がどのように機能するかという2つの点で、同様の誤解があります。 (1)それは同じ誤解ですか、(2)それをどのようにクリアするか(アンサーで、そして特にあなたがそのテーマについて好きなリファレンスを持っている場合)を理解する助けになりますか?ハスケルIOの割当を結合し分割するdoブロック

私は、すべて1行であれば正常に実行できますが、2つに分割して読みやすくするとできません。

パートI:2

に1行を回すと、なぜこの仕事をしますか?

ipg :: IO() 
ipg = do 
    conn <- connect defaultConnectInfo { connectHost = "0.0.0.0"} 
    res <- execute conn "INSERT INTO test (num, data) VALUES (?, ?)" $ MyRecord (Just 200) (Just"Test") 
    print res 

しかし、これは

ipg :: IO() 
ipg = do 
    conn <- connect defaultConnectInfo { connectHost = "0.0.0.0" } 
    q <- "INSERT INTO test (num, data) VALUES (?, ?)" $ MyRecord (Just 200) (Just"Test") 
    res <- execute conn q 
    print res 

に動作しない私を与える:

Couldn't match expected type ‘IO a0’ 
      with actual type ‘q0 -> IO GHC.Int.Int64’ 
Probable cause: ‘execute’ is applied to too few arguments 
In a stmt of a 'do' block: res <- execute conn q 

Qでクエリ部分を保存しようとする第一及び第二のビーイングの違いを。

パートII:1

に2行を回すと、なぜこの仕事ん:

myinput :: IO() 
myinput = do 
    putStrLn "Please input a number." 
    mynum :: Int <- readLn 
    print mynum 

しかし、これは動作しませんか?

myinput :: IO() 
myinput = do 
    mynum :: Int <- readLn $ putStrLn "Please input a number." 
    print mynum 

は私

execute conn "INSERT INTO test (num, data) VALUES (?, ?)" $ MyRecord (Just 200) (Just "Test") 

Couldn't match expected type ‘IO() -> IO Int’ 
      with actual type ‘IO a0’ 
The first argument of ($) takes one argument, 

答えて

4

を与え、$オペレータの左側はexecute conn "INSERT…"であり、右側はMyRecord …あります。つまり、接続、クエリ、およびパラメータの3つの引数を使用してexecuteを呼び出しています。ここで

q <- "INSERT INTO test (num, data) VALUES (?, ?)" $ MyRecord (Just 200) (Just "Test") 
res <- execute conn q 

$演算子の左側が文字列"INSERT…"で、右辺はパラメータである:それは、最初の問題です。あなたは文字列を呼び出しようとしており、その結果を第2引数としてexecuteに渡しています。

qが2つの引数を表現するいくつかの奇妙な型である場合、おそらくIO aではありません。 letで値を命名し、アクションを実行するのではなく、

これは動作するはずです:

ipg :: IO() 
ipg = do 
    conn <- connect defaultConnectInfo { connectHost = "0.0.0.0" } 
    let query = "INSERT INTO test (num, data) VALUES (?, ?)" 
    let parameters = MyRecord (Just 200) (Just "Test") 
    res <- execute conn query parameters 
    print res 

myinput :: IO() 
myinput = do 
    mynum :: Int <- readLn $ putStrLn "Please input a number." 
    print mynum 

この1つは、単に多くの意味がありません。おそらく$オペレータの誤解かもしれませんか?$は、ほとんどの場合、かっこを使用せずに式を書き込む方法です。 f $ xf xに相当しますが、$の優先度が低いため、f (1 + 2)の代わりにf $ 1 + 2と書くことができます。

ことができます場合はとにかく、私は緩く、あなたのためのPythonにそれを翻訳します:

def myinput(): 
    mynum = int(input(print("Please input a number."))) 
    print(mynum) 

あなたはreadLnputStrLnアクションをシーケンスする場合、あなたは何である(>>演算子を使用することができますdo舞台裏でやっている):

myinput :: IO() 
myinput = do 
    mynum :: Int <- putStrLn "Please input a number." >> readLn 
    print mynum 

これはほとんどの場合読みやすさにはあまり良くありません。 (()ではない何かを捨てる場合do { a; b }は、コンパイラの警告を与えるのに対し、a >> bも、文句なしaの結果を破棄します。)

+1

それを手に入れたので、これらは関係のない問題です。最初は、execute関数が4つの引数を取ったことをチェックしていなかったので、私がquery = "myquery {}"にする必要があったpythonの習慣です。実行する(照会する)。 2番目にはシーケンシャルオペレータが必要でした。 mynum :: Int < - (putStrLn "数字を入力してください。")>> readLn)$ thisを使用するよりも、明示的に操作の順序を示すために括弧が必要な場合は、 – Mittenchops