我有以下解析器函数
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
我收到错误。你能说出发生了什么吗?
答案 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
是从Char
到Bool
的函数;它不接受可能的解析结果列表。 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
阻止要求您的Parser
是Monad
类的实例。由于您的Parser
类型是函数类型String -> [(a, String)]
的别名,而函数不是Monad
的实例,因此这就是您收到错误的原因。您可以在不使用do
表示法的情况下编写函数:
sat :: (Char -> Bool) -> Parser Char
sat p [] = []
sat p (c:cs) = if p c then [(c, cs)] else []