0

我对 Haskell 和 Snap 还很陌生,我正在为一个使用 snap 的小型网络论坛开发自己的项目。我遇到的问题是理解冲突以及如何解决以下代码。

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;
           .... }

任何消除混淆的建议将不胜感激,我一直在寻找一些方法来解开可能并检索字节串,但没有成功。

非常感谢!

4

2 回答 2

3

Just是类型的构造函数Maybe agetParam,我很确定,返回Snap Maybe Bytestringsobs是 type Maybe 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

编辑

这取决于你想要做什么。Bind 很有用liftMlifM2, liftM3, 等也可以。

在您的情况下,您可能需要liftM2。我不知道你的类型是什么,但我会举一个非常简单的例子。保存你有那些 2 字节串你可以做这样的事情。

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

case (liftM2 append bs1 bs2) of
   Nothing -> writeBS "Failed"
   Just b  -> writeBS b
于 2013-07-29T18:43:20.187 回答
1

从类型中提取值的一种好方法Maybe a是使用模块中的fromMaybe函数Data.Maybe。如果您有一个默认值可Nothing用于Maybe.

我将在 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,我们可以将 type 设置a为 be Maybe ByteString,将 type设置b为 be IO 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

我们可以使用默认的 ByteString 部分应用 fromMaybe 并获得:

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

现在我们组合该函数return以将其ByteString放入IO

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

这是我们需要>>=在 的结果上使用的类型getParam1

由于我们在monad中的一个do块中,我们可以使用绑定箭头语法提取以供进一步使用:IOByteString<-

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

在这一点上,您可以按照自己认为合适的ByteString方式使用。str1do

希望这个解释对您有所帮助!

于 2013-08-12T18:55:45.910 回答