我正在将我(有限的)Haskell 知识应用到 Snap Web 框架中,看看我能构建什么。我正在尝试获取一个(可能不存在的)参数并将其解析为一个 int。显然“也许”是我想要的。
在下面的代码中AppHandler
定义为Handler App App
(我认为具有两个状态级别的 monad,尽管我现在在教程中找不到任何东西)。B8
是ByteString.Char8
和readInt
返回_Maybe(Int,ByteString)
下面的代码有效,但大概应该有一种方法将可能的调用链接在一起(大概是通过MaybeT,因为我已经在 Monad 中了)。链接特别有意义,因为下一步将根据解析的 id 从数据库中获取一行,所以当然这也会返回一个“Maybe a”。显然,这是一种非常普遍的模式。
-- Given a parameter name, return the Int it points to
-- or Nothing if there is some problem
maybeIntParam :: ByteString -> AppHandler (Maybe Int)
maybeIntParam pname = do
raw_param <- getParam pname
let mb_i_b = maybe (Nothing) B8.readInt raw_param
case mb_i_b of
Nothing -> return Nothing
Just (p,_) -> return $ Just p
我尝试应用 runMaybeT 但坦率地说,我没有真正了解需要更改的类型,我正在随机更改以希望错误消失。它没有,尽管它改变并从一行到另一行移动。
我将此视为进步,因为我现在完全迷失在一个比我开始探索 Haskell 时更高的水平......
编辑:遍历kosmikus的答案,希望我已经理解了...
1 maybeIntParam :: ByteString -> AppHandler (Maybe Int)
2 maybeIntParam pname = do
3 raw_param <- getParam pname
4 return $ do
5 param <- raw_param
6 (p, _) <- B8.readInt param
7 return p
我想我正试图朝着这个方向努力,但一直试图getParam
在与其他步骤相同的块内强行。
在第 3 行,对 getParam 的调用发生在 AppHandler 中。我们有 raw_param 这是一个Maybe ByteString
. 在第 5 行,我们在一个嵌套的 do 中,所以绑定(?)发生在 Maybe monadparam
中,要么是 aByteString
要么我们得到Nothing
,其余的 do 块将短路*。同样在第 6 行,p 要么是 Int,要么我们短路。
一切顺利,第 6 行p
包含一个 Int (比如 42),第 7 行将返回Just 42
. 回到第 4 行,变成AppHandler (Just 42)
. 现在不需要关心 AppHandler 是什么 - 类型都很高兴。
这里有一些变体也可以进行类型检查,并且可能证明对那些试图思考这一点的人有用。
maybeIntParam1 :: ByteString -> AppHandler (Maybe Int)
maybeIntParam1 pname = do
raw_param <- getParam pname
let mb_int_param = do
param <- raw_param
(p, _) <- B8.readInt param
return p
return mb_int_param
maybeIntParam2 :: ByteString -> AppHandler (Maybe Int)
maybeIntParam2 pname = do
return $ return 27
maybeIntParam3 :: ByteString -> AppHandler (Maybe Int)
maybeIntParam3 pname = do
return (Just 27)
在这种情况下,非执行变体实际上看起来更简单。唯一需要考虑的是<$>
,如果我没看错的话,它是公正fmap
的,并且适用于fst
,Maybe (Int,ByteString)
所以我们可以得到Maybe Int
。
*如果我理解正确,则必须访问后续每一行,但只返回 Nothing,因此实际上不是 goto 样式的快捷方式。 Edit2:请参阅下面的 kosmikus 评论 - 懒惰 + 右嵌套意味着我们不需要评估每一行。