我将我的(有限的)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 monad中,而param
将是ByteString
或者我们得到Nothing
,其余的do-block会短路 * 。同样在第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评论 - 懒惰+右嵌套意味着我们不需要评估每一行。
答案 0 :(得分:7)
您可以在本地使用Maybe
monad:
maybeIntParam :: ByteString -> AppHandler (Maybe Int)
maybeIntParam pname = do
raw_param <- getParam pname
return $ do
param <- raw_param
(p, _) <- B8.readInt param
return p
或者,如果您愿意,可以将Maybe
- 计算作为单行编写:
maybeIntParam :: ByteString -> AppHandler (Maybe Int)
maybeIntParam pname = do
raw_param <- getParam pname
return $ fst <$> (raw_param >>= B8.readInt)
涉及的一些类型:
raw_param :: Maybe ByteString
B8.readInt :: ByteString -> Maybe (Int, ByteString)
raw_param >>= B8.readInt :: Maybe (Int, ByteString)
fst :: (Int, ByteString) -> Int
fst <$> (raw_param >>= B8.readInt) :: Maybe Int