Haskell类型错误
考虑以下Haskell代码:Haskell类型错误,haskell,types,Haskell,Types,考虑以下Haskell代码: type Parser a = String -> [(a, String)] item :: Parser Char item = \ inp -> case inp of [] -> [] (x:xs) -> [(x, xs)] ret :: a -> Parser a ret v = \ inp -> [(v, inp)] parse ::
type Parser a = String -> [(a, String)]
item :: Parser Char
item = \ inp -> case inp of
[] -> []
(x:xs) -> [(x, xs)]
ret :: a -> Parser a
ret v = \ inp -> [(v, inp)]
parse :: Parser a -> String -> [(a, String)]
parse p inp = p inp
pseq :: Parser (Char, Char)
pseq = do x <- item
item
y <- item
ret (x, y)
ac = parse pseq "abcdef"
并且,当我删除“pseq”的类型声明时,会收到以下错误消息:
Type error in explicitly typed binding
*** Term : pseq
*** Type : [Char] -> [(([(Char,[Char])],[(Char,[Char])]),[Char])]
*** Does not match : Parser (Char,Char)
Unresolved top-level overloading
*** Binding : pseq
*** Outstanding context : Monad ((->) [Char])
问题是您试图使用
do
-表示法来表示解析器
,但它并不完全是单子。这有点像,因为r->
有一个Monad
实例,但这使得->
右侧的类型成为Monad
的“元素”类型,这里您希望元素类型是[(a,String)]
中的a
。您需要将解析器
定义为一个新类型
,并为它编写一个自定义的Monad
实例(或者使用现有的Monad/transformer,如ListT
和StateT
)来编写它。将解析器变成Monad很容易,而且我认为使用ListT或StateT在这里可能有点过头了
newtype Parser a = Parser (String -> [(a, String)])
-- make this a distinct type
-- now the function is "wrapped", though at no run-time cost
instance Monad Parser where
return = ret -- you already had it defined
(>>=) = bind -- added below
-- this instance makes Parser a Moand, and lets it work with do notation
item :: Parser Char
item = Parser $ \ inp -> case inp of
[] -> []
(x:xs) -> [(x, xs)]
-- need to "wrap" up the function as a Parser value
ret :: a -> Parser a
ret v = Parser $ \ inp -> [(v, inp)]
-- need to "wrap" up the function as a Parser value
bind :: Parser a -> (a -> Parser b) -> Parser b
bind p f = Parser $ \ s -> case parse p s of
[] -> []
[(a, s')] -> parse (f a) s'
-- the only function you were missing
-- it is worth making sure you understand how it works
parse :: Parser a -> String -> [(a, String)]
parse (Parser p) inp = p inp
-- needs to "unwrap" the newtype here
pseq :: Parser (Char, Char)
pseq = do x <- item
item
y <- item
ret (x, y)
ac = parse pseq "abcdef"
-- you probably meant pseq here, not seq
newtype解析器a=解析器(字符串->[(a,字符串)])
--让这成为一个独特的类型
--现在该函数已“包装”,但没有运行时成本
实例Monad解析器,其中
return=ret——您已经定义了它
(>>=)=绑定--添加到下面
--这个实例使解析器成为Moand,并允许它使用do符号
项::解析器字符
item=Parser$\inp->case inp of
[] -> []
(x:xs)->[(x,xs)]
--需要将函数“包装”为解析器值
ret::a->Parser a
ret v=Parser$\inp->[(v,inp)]
--需要将函数“包装”为解析器值
绑定::解析器a->(a->解析器b)->解析器b
bind p f=Parser$\s->case parse p s of
[] -> []
[(a,s')]->解析(f a)s'
--你唯一缺少的功能
--确保您了解它的工作原理是值得的
parse::Parser a->String->[(a,String)]
parse(Parser p)inp=p inp
--需要在此处“展开”新类型
pseq::解析器(Char,Char)
pseq=dox