代码之家  ›  专栏  ›  技术社区  ›  Dulguun Otgon

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

  •  2
  • Dulguun Otgon  · 技术社区  · 11 年前

    我正在翻第一版 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 回复  |  直到 10 年前
        1
  •  8
  •   Ørjan Johansen    11 年前

    您可以使用 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 ,这可以进一步缩短这一点,但需要一些无点性或另一个lambda:

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

    想一想,这可以与 getNat 也是:

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