Snap框架 - 重复可能整理

时间:2013-02-26 14:31:14

标签: haskell haskell-snap-framework maybe

我将我的(有限的)Haskell知识应用于Snap Web框架并查看我可以构建的内容。我正在尝试获取(可能不存在的)参数并将其解析为int。显然,“也许”就是我想要的。

在下面的代码中,AppHandler定义为Handler App App(我认为是一个具有两级状态的monad,尽管我现在在教程中找不到任何内容)。 B8ByteString.Char8readInt返回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评论 - 懒惰+右嵌套意味着我们不需要评估每一行。

1 个答案:

答案 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