haskell - Linter 说多余的 lambda,但是当按照建议替换时它会给出不同的错误

标签 haskell monad-transformers

我正在阅读 Real World Haskell - Chapter 10 .

所有函数都有共同的类型 L.ByteString -> Maybe (a, L.ByteString) 然后我查看了 StateT 定义,它是 s -> m (a, s) 如果写成 StateT L.ByteString Maybe a,它与上面完全匹配。所以我决定用 monad 转换器重写第一个例子。希望

parseP5 :: StateT L.ByteString Maybe Greymap
parseP5 = do
   matchHeader (L8.pack "P5")
   skipSpace
   width <- getNat
   skipSpace
   height <- getNat
   skipSpace
   maxGrey <- getNat
   skipSpace
   _ <- getBytes 1
   bitmap <- getBytes (width*height)
   return (Greymap width height maxGrey bitmap)

就可以了。

例如matchHeader函数会变成

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

但是 linter 说它有多余的 lambda。但是我不知道没有 lambda 怎么写。你能帮我解决这个问题吗?

更新:

当它被替换时:

matchHeader prefix str=
      if prefix `L8.isPrefixOf` str
         then Just ((), str)
         else Nothing

它给出了另一个错误

Couldn't match expected type L8.ByteString -> Maybe ((), L8.ByteString) with actual type StateT L8.ByteString Maybe () The equation(s) for matchHeader' have two arguments, but its type L8.ByteString -> StateT L8.ByteString Maybe () has only one

L8.ByteString -> Maybe((), L8.ByteString)StateT L8.ByteString Maybe () 不是一回事吗?

最佳答案

StateT s m a 不是 s -> m (a, s) 的类型别名,而是一个 newtype 包装器,它被算作一个通过类型检查器分离类型,因此您必须使用 StateT 构造函数包装您的 lambda。

import Control.Monad.State
import qualified Data.ByteString.Lazy as L
import qualified Data.ByteString.Lazy.Char8 as L8

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

您也可以使用 StateTMonad 实例编写没有 lambda 的匹配器

matchHeader prefix = do
      str <- get
      if prefix `L8.isPrefixOf` str
         then return ()
         else lift Nothing

这使用 get 获取当前状态,然后返回 () 或通过 StateT 转换器“提升”到内部 也许 monad.

上述示例使用与原始代码相同的逻辑,但您可能还想从状态中删除前缀。您还可以使用 MonadPlus 中的 guard 作为 Ørjan 演示来缩短 if 子句。

matchHeader :: L.ByteString -> StateT L.ByteString Maybe ()
matchHeader prefix = do
    str <- get
    guard (prefix `L8.isPrefixOf` str)
    put $ L8.drop (L8.length prefix) str

关于haskell - Linter 说多余的 lambda,但是当按照建议替换时它会给出不同的错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25237048/

相关文章:

haskell - 将数据类型定义为 MonadSample

haskell - 在 Web.Scotty 中使用 StateT

haskell - 各个角度的单子(monad)——数学的、图表的和程序化的

haskell - 在haskell中为元组列表分配等级

haskell - 为什么我的 MaybeT (State <type>) () 忽略状态更改?

javascript - 是否有有效的数组 monad 转换器?

Scalaz:过滤器在|@|中扮演什么角色?

haskell - 由于 (-1) 被视为负数,因此减法等于 (+1) 是什么?

haskell - 不将类型识别为转换器堆栈中 monad 的关联类型

haskell - 函数式编程的分析与设计