簡體   English   中英

清理Snap Route Handler(Haskell)

[英]Cleaning up Snap Route Handler (Haskell)

我正在使用針對haskell的snap框架創建一個站點,而且我仍然是haskell(和snap)的新手。 我希望找到一種“更好”的方式來編寫這個路由處理程序。

possibleMatches :: Snap ()
possibleMatches = do
  peptideSequence <- getParam "peptide_sequence"
  foundWeight     <- getParam "weight"
  let results = calculationResults (read . C8.unpack $ (fromJust foundWeight)) (fromJust peptideSequence)
  maybe (writeBS "must specify params in URL")
         writeJSON $ Just (results)

這里有幾件事:

  1. calculationResults有signature :: Float -> ByteString 我意識到我必須做一些事情才能將peptideSequenceMaybe ByteString變為ByteString ,所以這似乎是必要的(而且不是非常痛苦),但是
  2. Maybe ByteString轉換為Float似乎有點荒謬。 有沒有更好的方法來處理這個? 或者這只是需要被推入calculationResults函數的東西,並讓它處理轉換?

我想我正試圖從“學習泡沫中的哈斯克爾”中擴展到包括它是如何實際完成的,而不是在編譯器上敲擊它直到它最終放棄並說“好我會讓它通過”。

提前感謝您的意見!

一些東西。

fromJust只是非常邪惡。 這相當於純代碼世界中的unsafePerformIO 你正在從一個沒有模式匹配的Maybe monad中提取一個值。

fromJust :: Maybe a -> a
unsafePerformIO :: IO a -> a

> fromJust Nothing
*** Exception: Maybe.fromJust: Nothing

現在,賠率是你的HTML不會被惡意操縱,以便這些參數將返回Nothing 但是,如果確實發生了這種情況,你應該使用Snap的內置故障機制,它是Monad類的Snaps實現fail 它比fromJust更安全,並且由模式匹配失敗觸發。 您可以通過getParam上的模式匹配來使用它。 Just peptideSequence <- getParam "peptide_sequence"

instance Monad Snap where
    (>>=)  = snapBind
    return = snapReturn
    fail   = snapFail

snapFail實現為

snapFail :: String -> Snap a
snapFail !m = Snap $! return $! PassOnProcessing m

PassOnProcessing將優雅地處理模式匹配失敗。

更多信息在代碼中:

http://hackage.haskell.org/package/snap-core-0.8.0.1/docs/src/Snap-Internal-Types.html

邊注:

所有monad都有一個默認的fail實現,但如果沒有覆蓋,結果往往是不受歡迎的。 任何不受歡迎的我都意味着它會拋出一個只能在IO monad中捕獲的異常,但是如果你不是在IO monad中運行,那么你運氣不好。 Snap已覆蓋默認的fail實現。

來自RWH:

小心失敗。 許多Monad實例不會覆蓋我們在此處顯示的默認失敗實現,因此在這些monad中,fail使用錯誤。 調用錯誤通常是非常不受歡迎的,因為它會拋出一個異常,即調用者無法捕獲或不期望。

即使你現在知道你在一個失敗的monad中執行更合理的事情,我們仍然建議避免它。 當您重構代碼並忘記以前安全使用失敗在新環境中可能是危險的時候,很容易讓自己成為一個問題。

我仍然使用它,因為它在這種情況下是有意義的(除非Snap作者想要糾正我)

我會得到CalculationResults的結果返回一個JSON結果。 我還會在CalculationResults函數中處理Float類型轉換,可能會使它更清晰

possibleMatches :: Snap ()
possibleMatches = do
  Just peptideSequence <- getParam "peptide_sequence"
  Just foundWeight     <- getParam "weight"
  writeJSON $ calculationResults (read $ C8.unpack foundWeight) peptideSequence

要么

possibleMatches :: Handler App (AuthManager App) ()
possibleMatches = do
  (peptideSequence, foundWeight) <- (,) <$> getParam "peptide_sequence" <*> getParam "weight"
  writeJSON $ calculationResults (read $ C8.unpack foundWeight) peptideSequence

更新:

要在Snap中進行更強大的錯誤處理,您可以使用以下代碼:

catchError :: HasHeist b => ByteString -> Handler b v () -> Handler b v ()
catchError msg action = action `catch` \(e::SomeException) -> go
    where go = do logError msg
                  modifyResponse $ setResponseCode 500
                  render "500"

其中“500”是位於snaplets/heist/templates/500.tpl中的文件"500.tpl"的名稱要將其應用於您的一個處理程序,您可以執行以下操作:

handleNewUser :: Handler App (AuthManager App) ()
handleNewUser = method GET handleGet <|> method POST handlePost
  where
    handleGet = currentUser >>= maybe the404 (\_ -> render "profile")
    handlePost = catchError "Error during login" $ do
          setTimeout 100
          Just login <- getParam "login"
          if | isValid login -> do user <- registerUser "login" "password"
                                   either (\_ -> render "error") (handleUser login) user
             | otherwise -> render "error"
    handleUser = -- etc etc

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM