haskell中简单解析器的示例

时间:2014-12-30 20:01:50

标签: parsing haskell

我有以下解析器函数

import Data.Char
type Parser a = String -> [(a,String)]

return' :: a -> Parser a
return' v = \inp -> [(v,inp)]

failure :: Parser a
failure = \inp -> []

item :: Parser Char
item = \inp -> case inp of
         [] -> []
     (x:xs) -> [(x,xs)]

parse :: Parser a -> String -> [(a,String)]
parse p inp = p inp

parse :: Parser a -> String -> [(a,String)]
parse p inp = p inp

(+++) :: Parser a -> Parser a -> Parser a
p +++ q = \inp -> case parse p inp of
            [] -> parse q inp
     [(v,out)] -> [(v,out)]

到目前为止,它们可以加载到ghci中。但是当我添加以下功能时

sat :: (Char -> Bool) -> Parser Char
sat p = do x <- item
           if p x then return x else failure

我收到错误。你能说出发生了什么吗?

2 个答案:

答案 0 :(得分:1)

x do区块中sat的类型为[(Char, String)]。这是因为item的类型为String -> [(Char, String)](->) String [(Char, String)],您使用Monad的{​​{1}}实例,因此(->) String中包含的内容是(->) String [(Char, String)] 1}}是[(Char, String)]

{-# LANGUAGE ScopedTypeVariables #-}

sat :: (Char -> Bool) -> Parser Char
sat p = do (x :: [(Char, String)]) <- item
           if p x then return' x else failure

p是从CharBool的函数;它不接受可能的解析结果列表。 p唯一明智的做法是filter根据Char是否与p匹配的结果。当结果与[]不匹配时,这仍会导致p

sat :: (Char -> Bool) -> Parser Char
sat p = do (x :: [(Char, String)]) <- item
           return $ filter (p . fst) x

如果我们删除ScopedTypeVariables,我们需要删除我添加的类型签名以供说明。

sat :: (Char -> Bool) -> Parser Char
sat p = do x <- item
           return $ filter (p . fst) x

答案 1 :(得分:0)

使用do阻止要求您的ParserMonad类的实例。由于您的Parser类型是函数类型String -> [(a, String)]的别名,而函数不是Monad的实例,因此这就是您收到错误的原因。您可以在不使用do表示法的情况下编写函数:

sat :: (Char -> Bool) -> Parser Char
sat p [] = []
sat p (c:cs) = if p c then [(c, cs)] else []