2013-07-29 42 views
0

我對Haskell和Snap相當新,我正在通過我自己的項目爲小型網絡論壇使用管理單元。我遇到的問題是瞭解衝突以及如何解決以下代碼。哈斯克爾Snap框架 - 類型不匹配ByteString /也許ByteString

handleCategoryAdd :: H() 
handleCategoryAdd = method POST (withLoggedInUser go) 
    where 
    go user = do 
     bs <- getParam "categoryName" 
     cN <- B.unpack $ Just bs 
     cD <- getParam "categoryDesc" 
     cT <- getCurrentTime 
     return (Db.saveCategory (Db.Category 1 cN cT "1")) 
     redirect "/" 

給了我一個類型不匹配錯誤如下:

src\Site.hs:118:22: 
    Couldn't match expected type `ByteString' 
       with actual type `Maybe ByteString' 
    In the first argument of `unpack', namely `bs' 
    In a stmt of a 'do' block: cN <- unpack bs 
    In the expression: 
     do { bs <- getParam "categoryName"; 
      cN <- unpack bs; 
      cD <- getParam "categoryDesc"; 
      cT <- getCurrentTime; 
      .... } 

任何意見,清理混亂將不勝感激,我一直在尋找一些方法來或許解開了,只是檢索字節串,但不成功。

非常感謝!

回答

3

JustMaybe a類型的構造函數。 getParam,我很確定,返回Snap Maybe Bytestring所以bsMaybe Bytestring類型。當你說Just bs你然後將有Maybe (Maybe Bytestring)這顯然是你不想要的。您正在尋找fromJust :: Maybe a -> a,但此功能是危險的,因爲如果getParam甚至已經成功,並且在具有該名稱的html頁面上有輸入,您還沒有檢查。

你應該做的是用例或>>=

喜歡的東西

bs <- getParam "categoryName" 
case bs of 
    Nothing -> writeBS "failed" 
    Just b -> do 
     let unpacked = B.unpack b 
     -- ... Do more stuff 

編輯

這取決於你正在嘗試做的。綁定可以是有用的,所以可以liftM,lifM2,liftM3

在你的情況下,你可能想liftM2。我不知道你的類型是什麼,但我會舉一個非常簡單的例子。保存你有這些2 Bytestrings你可以做這樣的事情。

bs1 <- getParam "one" 
bs2 <- getParam "two" 

case (liftM2 append bs1 bs2) of 
    Nothing -> writeBS "Failed" 
    Just b -> writeBS b 
+0

歡呼,這有助於! – stickybynature

+0

你會如何使用>> =在這種情況下? – stickybynature

1

Maybe a類型中提取的值的最好方法是使用fromMaybe函數從Data.Maybe模塊。如果Maybe中的值爲Nothing,則有一個默認值可用。

我將在IO monad中提供一個示例,而不是一些Snap monad,以避免拉動Snap庫以使演示代碼正常工作,但它應該與長時間一樣工作(除了類型簽名更改)因爲處理程序與getParam操作處於相同單子中。

{-# LANGUAGE OverloadedStrings #-} 
import   Data.Maybe 
import   Data.ByteString.Char8 (ByteString) 
import qualified Data.ByteString.Char8 as B 

getParam1, getParam2 :: IO (Maybe ByteString) 
getParam1 = return $ Just "Hello" 
getParam2 = return $ Nothing 

main :: IO() 
main = do 
    str1 <- getParam1 >>= return . fromMaybe "No value" 
    str2 <- getParam2 >>= return . fromMaybe "No value" 

    B.putStrLn str1 
    B.putStrLn str2 

由於getParam1getParam2IO (Maybe ByteString),我們知道我們需要使用一元行動在Maybe ByteString值進去。

通過查看>>=類型的簽名,這是m a -> (a -> m b) -> m b,我們可以設置類型aMaybe ByteString並鍵入bIO ByteString,這意味着我們正在尋求與這些特定類型的應用綁定:

-- (Type of getParam1 >>= Type of our function to supply) -> Desired type 
IO (Maybe ByteString) -> (Maybe ByteString -> IO ByteString) -> IO ByteString 

考慮到這一點,我們可以看看fromMaybe類型:

fromMaybe :: a -> Maybe a -> a 

我們可以部分地適用fromMaybe有一個默認的字節串,並得到:

fromMaybe "No value" :: Maybe ByteString -> ByteString 

現在我們撰寫與return該功能把ByteStringIO

return . fromMaybe "No value" :: Maybe ByteString -> IO ByteString 

這是我們需要對getParam1結果使用>>=類型。

由於我們是在IO單子一個do塊,我們可以使用<-結合箭頭語法進一步使用提取ByteString

str1 <- getParam1 >>= return . fromMaybe "No value" 

在這一點上,你有str1ByteString到請按照您在do區塊中所見的方式使用。

希望你覺得這個解釋很有幫助!