印刷するために名前を聞いて、書き直してみようと想像できます。
擬似コードでは、
main =
print "what is your name"
bind varname with userReponse
print varname
次に、あなたの質問は2番目の指示に関するものです。
これのセマンティクスについて見てみましょう。
- userReponseは、ユーザー入力を返す関数です(getLine)
- varnameはvarです
- var を funでバインド:var(varname)をfunction(getLine)の出力に関連付ける関数です
または、haskellでご存知のように、すべてが関数であるため、セマンティクスはあまり適していません。
このイディオムを尊重するために、それを再検討する必要があります。後の反射によると、バインド関数のセマンティクスは、楽しくバインドするようになり ます
変数を持つことはできないので、関数に引数を渡すには、一見したところ、それらを生成するために別の関数を呼び出す必要があります。したがって、2つの関数をチェーンする方法が必要であり、それはまさにバインドが行うことになっていることです。さらに、この例が示すように、評価順序を尊重する必要があります。これにより、次のように 楽しい バインド 楽しい書き直しが可能になります。
これは、バインドがそれが演算子である関数以上のものであることを示唆しています。
次に、すべての関数fとgについて、fbindgを使用します。
haskellではこれを次のように記しています
f >>= g
さらに、関数が0、1以上の引数を取り、0、1以上の引数を返すことがわかっているように。バインド演算子
の定義を改良することができます。
実際、fが結果を返さない場合は、>> = as >>
を適用すると、擬似コードへのこれらの反射により、次のようになります。
main = print "what's your name" >> getLine >>= print
ちょっと待ってください。バインド演算子は、2つの関数の合成に使用するドット演算子とどのように異なりますか?
重要な情報を省略しているため、バインドは2つの関数をチェーンしませんが、2つの計算ユニットをチェーンします。これが、この演算子を定義した理由を理解するための要点です。
グローバル計算を計算単位のシーケンスとして書き留めましょう。
f0 >>= f1 >> f2 >> f3 ... >>= fn
この段階では、グローバル計算は、2つの演算子>> =、>>を持つ計算ユニットのセットとして定義できます。
コンピュータサイエンスのセットをどのように表現しますか?
通常はコンテナとして。
その場合、グローバル計算は、いくつかの計算単位を含むコンテナーです。このコンテナでは、後者の結果を考慮に入れて、または考慮せずに、計算ユニットから次のユニットに移動できる演算子を定義できます。これは、私たちの>>=および>>演算子です。
これはコンテナであるため、値を注入する方法が必要です。これは、 return関数によって実行されます。オブジェクトを取得して計算に注入するものは、署名であるかどうかを確認できます。
return :: a -> m a -- m symbolize the container, then the global computation
これは計算であるため、失敗を管理する方法が必要です。これは、fail関数によって実行されます。実際、計算
のインターフェースはクラスによって定義されます
class Computation
return -- inject an objet into a computation
>>= -- chain two computation
>> -- chain two computation, omitting the result of the first one
fail -- manage a computation failure
これで、次のようにコードを改良できます。
main :: IO ()
main = return "What's your name" >>= print >> getLine >>= print
ここでは、メイン関数のシグネチャを意図的に含めて、グローバルIO計算に参加しているという事実と、結果の出力をbe ()で表現しています(演習として、ghciに$:t printと入力します)。>> =
の定義にさらに焦点を当てると、次の構文が出現する可能性があります
f >>= g <=> f >>= (\x -> g) and f >> g <=> f >>= (\_ -> g)
そして、
main :: IO ()
main =
return "what's your name" >>= \x ->
print x >>= \_ ->
getLine >>= \x ->
print x
ご想像のとおり、計算環境でバインド演算子を処理するための特別な構文があります。そうです、これがdo構文の目的です。
次に、前のコードはdo構文になります。
main :: IO ()
main = do
x <- return "what's your name"
_ <- print x
x <- getLine
print x
もっと知りたい場合はモナドを見てください
leftaroundaboutで述べたように、私の最初の結論は少し熱狂的すぎました
参照透過性の法則(xは命令のシーケンス内で2つの異なる値を取ります)があるので、ショックを受けるはずですが、計算に入っているので、もう問題ではありません。後で定義される計算は、これはインターフェースを導き出すことができ、このインターフェースは、説明するように、現実の世界に対応する 不純な世界を管理するように設計されています。