Linter说多余的lambda,但如果按照建议更换它会产生不同的错误

时间:2014-08-11 06:30:14

标签: 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

它给出了另一个错误

  

无法匹配预期类型L8.ByteString -> Maybe ((), L8.ByteString)   实际类型StateT L8.ByteString Maybe ()   matchHeader&#39;的等式有两个参数,但它的类型   L8.ByteString -> StateT L8.ByteString Maybe ()只有一个

Isn&#t; t L8.ByteString -> Maybe((), L8.ByteString)StateT L8.ByteString Maybe ()同样的事情?

1 个答案:

答案 0 :(得分:7)

StateT s m a不是s -> m (a, s)的类型别名,而是newtype包装器,由类型检查器计为单独的类型,因此您必须使用{{包装lambda 1}}构造函数。

StateT

您还可以使用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 <{1}} Monad实例编写不带lambda的匹配器

StateT

这使用matchHeader prefix = do str <- get if prefix `L8.isPrefixOf` str then return () else lift Nothing 来获取当前状态,然后返回get或“提升”()转换器到内部StateT monad。

上面的示例使用与原始代码相同的逻辑,但您可能还希望从状态中删除前缀。您也可以使用来自Maybe的{​​{1}},因为Ørjan已经证明可以缩短if子句。

guard