如何在没有lambda表达式的情况下编写这些

时间:2014-08-11 08:38:55

标签: haskell lambda monad-transformers

我正在使用this code的第一个版本来使用StateT L8.ByteString Maybe a。到目前为止,我已将大部分功能转化为此

matchHeader :: L8.ByteString -> StateT L8.ByteString Maybe ()
matchHeader prefix = StateT $ \str ->
      if prefix `L8.isPrefixOf` str
         then Just ((), L8.drop (L8.length prefix) str)
         else Nothing

getNat :: Num a => StateT L8.ByteString Maybe a
getNat = StateT $ \str ->
  case L8.readInt str of
    Nothing -> Nothing
    Just (num, rest)
      | num <= 0        -> Nothing
      | otherwise       -> Just (fromIntegral num, rest)

getBytes :: Integer -> StateT L8.ByteString Maybe L8.ByteString
getBytes n = StateT $ \str ->
  let
    count = fromIntegral n
    both@(prefix, _) = L8.splitAt count str
   in if L8.length prefix < count
        then Nothing
        else Just both

但是如何在不使用lambda表达式的情况下编写这些内容?我尝试了一些变化。到目前为止没有运气。

1 个答案:

答案 0 :(得分:8)

您可以使用do表示法和状态/ monad操作。例如:

getNat :: Num a => StateT L8.ByteString Maybe a
getNat = do
  num <- StateT L8.readInt
  guard (num > 0)
  return (fromIntegral num)

编辑:根据请求,尝试getBytes

getBytes :: Integer -> StateT L8.ByteString Maybe L8.ByteString
getBytes n = do
  let count = fromIntegral n
  prefix <- state $ L8.splitAt count
  guard (L8.length prefix >= count)
  return prefix

:browse - Control.Monad时,我还发现了(有点新的?)函数mfilter,这可能会进一步缩短这一点,但需要一些点免费或其他拉姆达:

getBytes n = do
  let count = fromIntegral n
  mfilter ((>= count) . L8.length) . state $ L8.splitAt count

考虑一下,它也适用于getNat

getNat = fromIntegral <$> mfilter (> 0) (StateT L8.readInt)