4

これは、いくつかの質問を 1 つにまとめたものです。

  1. do記法では、各行は同じ型を返す必要がありますか? たとえばdo、モナドを返す 1 つのブロックに 1 つの行を書きIO、整数を返す別の行を書くことはできますか? (私の理解では、 と を使用した脱糖がどのように機能しているように見えるかに基づい>>>>=、答えはノーです。)

  2. そうでない場合、コンパイラは行がすべて返す必要がある型をどのように決定しますか? IO私が見たすべての例で、著者は、モナドを扱っているだけだということを当然の結論として受け入れています。doしかし、特定のブロックについて、各行が何を返さなければならないかをどうやって知るのでしょうか?

  3. doもう一度 #1 の答えがノーであると仮定します:ブロック内で正しい種類のモナドを返さない関数をどのように使用しますか? たとえば、次の websockets コードを考えてみましょう。

    application :: MVar ServerState -> WS.Request -> WS.WebSockets WS.Hybi00 ()
    application state rq = do
      WS.acceptRequest rq
      msg <- WS.receiveData :: WS.WebSockets WS.Hybi00 Text
      return ()
    

    の値を出力したいとしますmsgdoブロックのタイプと競合しない方法でそれを行うにはどうすればよいですか?

4

2 に答える 2

9
  1. do ブロックでは、各行は異なる型を返すことができますが、それらは同じモナド内にある必要があります
    • 1 つの行は を返すことができ、1 つの行は を返すことがIO StringできますIO Integerが、両方とも である必要がありますIO
  2. 残りの Haskell と同じです。型推論。Haskell の他の部分と同様に、常に機能するとは限りません。機能しない場合は、同様に注釈を付ける必要があります。
  3. これを行うには2つの方法があります
    • letdo、GHCi で let を使用してローカル変数を宣言する必要があることを思い出してください。ブロックでも同じことができます。let someMonad = doSomething
      • 注意、いいえin
    • モナドトランスフォーマー!これは宣伝文句で説明する大きなトピックですが、基本的には、lift別のモナドをトランスフォーマーに「持ち上げる」ことができる特別な機能を持つモナドです。トランスフォーマーは通常、StateT などの T で終わります。使用するほとんどすべてのモナドには、同等の変換子があります。
于 2013-05-15T04:40:35.373 に答える
4

最後の質問の最後の部分に答えるには、

の値を出力したいとしますmsgdoブロックのタイプと競合しない方法でそれを行うにはどうすればよいですか?

jozefg が彼の答えで言ったように、モナドトランスフォーマーは通常、これに必要なものです。ただし、この場合、WebSockets pモナドは変換子ではありません。しかし、それは「最下部」にMonadIOあるモナド スタックのクラスのインスタンスであり、したがって、その中から任意のアクションを実行できます。IOIO

MonadIOクラスは、liftIO型を持つ関数を提供します

liftIO :: MonadIO m => IO a -> m a

あなたの場合、これは になるので、それを使用してアクションを からにIO a -> WebSockets Hybi00 a変換できます。これをブロックで使用できます。print msgIO ()WebSockets Hybi00 ()do

application :: MVar ServerState -> WS.Request -> WS.WebSockets WS.Hybi00 ()
application state rq = do
  WS.acceptRequest rq
  msg <- WS.receiveData :: WS.WebSockets WS.Hybi00 Text
  liftIO $ print msg
于 2013-05-15T11:20:51.430 に答える