2016-12-24 32 views
1

私はwaiアプリケーションの基本的なディスパッチセクションに従っています。IO内部アプリケーションを実行

私はurlパラメータをキャッチすることができます。これらのパラメータを使用してIO操作を実行するにはどうすればよいですか。

これらのパラメータを使用してシステムコマンドを実行するには、System.ProcessのrunCommandを使用します。

:runCommand関数をtあなたのデザインは、なぜならあなたがappを書かれている方法で、すぐにあなたと言う

app request respond = respond $ case rawPathInfo request of 

それを防ぐ runCommand :: String -> IO ProcessHandle

私のMain.hs

{-# LANGUAGE OverloadedStrings #-} 

module Main where 
import Control.Monad 
import Network.Wai 
import Network.HTTP.Types 
import Network.Wai.Handler.Warp (run) 
import Data.ByteString 
import Control.Monad 
import System.Process 
import qualified Data.ByteString.Lazy.Char8 as L8 

main :: IO() 
main = do 
    run 8080 app 

app :: Application 
app request respond = respond $ case rawPathInfo request of 
    "/" -> indexHtml 
    "/wake" -> wakeMeUP request 
    _ -> fourNotFour 

indexHtml :: Response 
indexHtml = responseFile 
    status200 
    [("Content-Type","text/html")] 
    "index.html" 
    Nothing 

wakeMeUP :: Request -> Response 
wakeMeUP request = 
    let query = queryString request 
     hour = join $ lookup "hour" query 
     min = join $ lookup "min" query 
    --I would like to use runCommand "using hour and min variables" 
    in responseLBS 
     status200 
     [("Content-Type","text/plain")] 
     "Alarm set at...to be coded later" 

fourNotFour :: Response 
fourNotFour = responseLBS 

    status404 
    [("Content-Type","text/plain")] 
    "404 not found" 

答えて

2

を与えます応答する。 Applicationの種類に注意してください。

type Application = Request -> (Response -> IO ResponseReceived) -> IO ResponseReceived 

結果の型はIOを持っているので、あなたが価値をもたらす前にI/Oを行うための機会を持っています。だから、可能性:

app request respond = do 
    whateverResult <- runCommand "whatever" 
    respond $ ... 

(あなたはまた、少なくとも種類に応じて、後でそれを行うことができます:

app request respond = do 
    rcvd <- respond $ ... 
    runCommand "whatever" 
    return rcvd 

それがここで使用されている継続渡しイディオムのために行うには少し奇妙だけど(Applicationタイプの(a -> b) -> bパターン)。つまり、waiソースを読み取らずにわからない "その他すべて"の定義のために、コマンドは他のものの後に実行されることを意味します)。

とにかく、appの中でコマンドを実行するのではなく、wakeMeUpというコマンドを実行することをお勧めします。つまり、いくつかのタイプを変更する必要があります。具体的には、

wakeMeUp :: Request -> IO Response 
--      ^^ 

であり、適切に機能をモノ化する。あなたはこれがあなたにちんぷんかんぷんであれば、それはいくつかのモナドチュートリアルを行うには時間だ

app request respond = 
    response <- case rawPathInfo request of 
     "/" -> return indexHtml 
--   ^^^^^^ 
     "/wake" -> wakeMeUp request 
--  no change, because wakeMeUp now has an IO return type 
     ... 
    respond response 

を言うことができますので、すぐにrespondを呼び出さないと、あなたのappニーズ。まあ、ダン・ピポニのThe IO Monad For People who Simply Don't Careをお勧めします。ハッピーハッキング!

+0

ありがとうございました。それは完璧な意味合いがあります。私は質問を投稿した後、同様の解決策に達しました。しかし私のコードでは、ルートコードを緩めなければならなかった。私はモナドを理解するが、私はIOのより多くの運動をする必要があることを認識した。 –

関連する問題