1

私はこの概念に迷っています。これは私のコードであり、それが行うことはあなたの名前を尋ねるだけです。

askName = do
  name <- getLine
  return ()

main :: IO ()
main = do
       putStrLn "Greetings once again.  What is your name?"
       askName

mainただし、 askNameで取得した変数名にアクセスするにはどうすればよいですか?

これは私の2回目の試みです:

askUserName = do
  putStrLn "Hello, what's your name?"  
  name <- getLine  
  return name

sayHelloUser name = do
  putStrLn ("Hey " ++ name ++ ", you rock!")

main = do
  askUserName >>=  sayHelloUser

これで、コールバックの方法でを再利用できますがname、メインで名前を再度呼び出したい場合は、どうすればよいですか?name <- getLine (明らかに、メインに入れるのを避けます)

4

2 に答える 2

6

印刷するために名前を聞いて、書き直してみようと想像できます。
擬似コードでは、

main =   
    print "what is your name"  
    bind varname with userReponse    
    print varname  

次に、あなたの質問は2番目の指示に関するものです。
これのセマンティクスについて見てみましょう。

  1. userReponseは、ユーザー入力を返す関数です(getLine)
  2. varnameはvarです
  3. 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つの異なる値を取ります)があるので、ショックを受けるはずですが、計算入っているので、もう問題ではありません。後で定義される計算は、これはインターフェースを導き出すことができ、このインターフェースは、説明するように、現実の世界に対応する 不純な世界を管理するように設計されています。

于 2013-01-07T23:42:28.313 に答える
3

asknameから名前を返します。Haskellでは、「グローバル」変数にアクセスするのは慣用的ではありません。

askName :: IO String
askName = do
  name <- getLine
  return name

main :: IO ()
main = do
       putStrLn "Greetings once again.  What is your name?"
       name <- askName
       putStrLn name

現在、唯一の問題は、askName関数が無意味であるということです。これは、のエイリアスにすぎないためgetLineです。質問をaskName内に置くことで、これを「修正」できます。

askName :: IO String
askName = do
  putStrLn "Greetings once again.  What is your name?"
  name <- getLine
  return name

main :: IO ()
main = do
       name <- askName
       putStrLn name

最後に、2つの小さなポイントがあります。通常、学習時に型宣言を配置し、物事を明示的にして、コンパイラのエラーメッセージを支援することをお勧めします。もう1つのことは、「return」関数はモナディックコードにのみ使用され(従来のreturnステートメントとは類似していません!)、いくつかの中間変数を省略できる場合があることを覚えておいてください。

askName :: IO String
askName = do
  putStrLn "Greetings once again.  What is your name?"
  getLine
于 2013-01-07T18:47:04.627 に答える