我对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;
.... }
任何清除混淆的建议都会非常感激,我一直在寻找一些解开may的方法,只是检索字节串但是没有成功。
非常感谢!
答案 0 :(得分:3)
Just
是Maybe a
类型的构造函数。 getParam
,我非常确定,返回Snap Maybe Bytestring
,因此bs
的类型为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
修改强>
这取决于你想要做什么。绑定可能很有用,因此可以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
答案 1 :(得分:1)
从Maybe a
类型中提取值的一种好方法是使用fromMaybe
模块中的Data.Maybe
函数。如果您在Nothing
中有Maybe
值的情况下使用默认值,则非常有用。
我将在IO monad而不是一些Snap monad中提供一个示例,以避免拉入Snap库以使演示代码工作,但它应该工作相同(除了类型签名更改),只要处理程序与getParam
操作位于同一个monad中。
{-# 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
由于getParam1
和getParam2
是IO (Maybe ByteString)
,我们知道我们需要使用monadic动作来获取内部的Maybe ByteString
值。
通过查看>>=
的{{1}}类型签名,我们可以将m a -> (a -> m b) -> m b
类型设置为a
,并将Maybe ByteString
类型设置为{ {1}},这意味着我们希望将绑定应用于这些特定类型:
b
考虑到这一点,我们可以查看IO ByteString
的类型:
-- (Type of getParam1 >>= Type of our function to supply) -> Desired type
IO (Maybe ByteString) -> (Maybe ByteString -> IO ByteString) -> IO ByteString
我们可以使用默认的ByteString部分应用fromMaybe并获取:
fromMaybe
现在我们使用fromMaybe :: a -> Maybe a -> a
撰写该功能,将fromMaybe "No value" :: Maybe ByteString -> ByteString
放回return
:
ByteString
这是我们在IO
的结果上使用return . fromMaybe "No value" :: Maybe ByteString -> IO ByteString
所需的类型。
由于我们位于>>=
monad的getParam1
块中,因此我们可以使用do
绑定箭头语法提取IO
以供进一步使用:
ByteString
此时,<-
中的str1 <- getParam1 >>= return . fromMaybe "No value"
纯ByteString
可以在str1
区块中使用。
希望您觉得这个解释很有帮助!