在Haskell中接受/拒绝下推自动机

时间:2018-11-17 18:50:03

标签: haskell recursion pushdown-automaton

我正在尝试在Haskell中创建下推式自动机检查。基本上,一个函数使用(start_state, final_state, set_of_rules) and a string。如果此PDA接受了字符串,则应返回Accepted,否则返回Rejected

这是我到目前为止所拥有的:

type Transition = ((Int,String,String),(Int,String))

type Configuration = (Int,String,String)

type PDA = (Int,[Int],[Transition])

data Result = Accept | Reject | Jj deriving Show

run :: PDA -> String -> [Result]
run (ss,fs,tr) xs = runs (ss,fs,tr) (ss,xs,"")

runs :: PDA -> Configuration -> [Result]
-- When string and stack empty accept
runs _ (_,[],[]) = [Accept]
-- If string empty and stack not empty, reject
runs _ (_,[],_) = [Reject]
runs z@(ss,fs,tt) (cs,(x:xs),st) = [runs z (d,xs,e) | m@((a,b,c),(d,e)) <- [xf | xf@((a,b,c),(d,e)) <- tt, a == cs, b == [x]]]

最后一行是我的逻辑中断的地方,我想解释一下:

[xf | xf@((a,b,c),(d,e)) <- tt, a == cs, b == [x]]

这需要一组规则(tt)并列出在当前状态(cs)和字符串开头匹配的地方我可以使用的所有规则。这可以完美工作并列出所有可能的动作。我想使用此列表的每个元素,然后再次通过此函数运行它。当达到基本情况时,我会根据堆栈状态返回“接受”或“拒绝”。

我期望看到的是一个充满Reject的列表,因为我实际上还没有使用堆栈。

我一直都在遇到Couldn't match type ‘[Result]’ with ‘Result’的编译错误,但无法修复。任何帮助都非常感激

1 个答案:

答案 0 :(得分:3)

问题在于,在递归子句中:

runs :: PDA -> Configuration -> [Result]
-- ...
runs z@(ss,fs,tt) (cs,(x:xs),st) = [runs z (d,xs,e) | ... ]

您违反了类型合同。实际上,runs应该返回Result的列表。但是在您的表达式中,您构造了runs的结果列表(以及runs z (d, xs, e)的列表,因此这意味着该列表理解是在构造Results的列表,而不是结果列表。

因此,我们需要将这些子列表“串联”为一个平面列表,例如使用concat :: [[a]] -> [a],并使用:

runs :: PDA -> Configuration -> [Result]
-- When string and stack empty accept
runs _ (_,[],[]) = [Accept]
-- If string empty and stack not empty, reject
runs _ (_,[],_) = [Reject]
runs z@(ss,fs,tt) (cs,(x:xs),st) = concat [runs z (d,xs,e) | m@((a,b,c),(d,e)) <- [xf | xf@((a,b,c),(d,e)) <- tt, a == cs, b == [x]]]