所以我试图用f#来查找一个字符串是否有匹配的括号。 即:(abc)返回true,((hello)返回false,并且)(返回false,等等......
我(我想)正在做的是在列表中看到'('和pop,当它看到')'时使用堆栈进行推送。然后,如果字符串列表为空,则堆栈有一个项目,或者它没有。如果是,那么我说它是无效的,如果我遇到一个')'并且堆栈是空的,它也是无效的。否则它是一个有效的字符串。
// Break string
let break_string (str:string) =
Seq.toList str
let isBalanced (str:string) =
let lst = break_string str
let stack = []
let rec balance str_lst (stk:'a list)=
match str_lst with
| [] ->
if stk.Length > 0 then
false
else
true
| x::xs ->
if x = '(' then
balance (xs x::stack)
elif x = ')' then
if stack.Length = 0 then
false
else
stack = stack.tail
balance (lst, stack)
我对f#很新,所以我认为这可能正在做我想要的,但是我收到错误消息: “这个表达式预计会有bool类型,但这里有类型'a list - > bool”
首先,这究竟意味着什么? 第二,既然它正在返回一个布尔,那为什么不起作用呢?
答案 0 :(得分:2)
类型检查器认为您忘记了balance
的第二个参数。当你这样写:
balance (xs x::stack)
这意味着"将balance
应用于{将xs
应用于x::stack
)"。你可能意味着这个:
balance xs (x::stack)
您的最终elif
似乎也错过了else
分支,而stack = stack.tail
行看起来像是您尝试分配给stack
。你不能这样做,因为stack
是一个不可变的变量。可能你想要balance xs (List.tail stack)
。原则是,您可以使用新值调用函数,而不是分配给变量。
当然,你有正确的想法。通过将所有匹配(字母是什么?堆栈中的内容?)折叠成一个单个匹配语句,可以更加简洁。诀窍是将您想要查看的所有内容放入单个元组中:
let isBalanced str =
let rec loop xs stack =
match (xs, stack) with
| '(' :: ys, stack -> loop ys ('(' :: stack)
| ')' :: ys, '(' :: stack -> loop ys stack
| ')' :: _, _ -> false
| _ :: ys, stack -> loop ys stack
| [], [] -> true
| [], _ -> false
loop (Seq.toList str) []