我在理解以下功能时遇到了问题
lines :: String -> [String]
lines "" = []
lines ('\n':cs) = "": lines cs
lines (c:cs) = case lines cs of
[] -> [[c]]
(l:ls) -> (c:l):ls
我想了解"f\no"
调用函数时的功能。我正在寻找一个工具,显示每个替换步骤,以便更好地理解该功能。我手动尝试(并在写这篇文章时得到了解决方案),但我不确定我是否正确。
lines ('f':"\no") = case lines "\no" of
[] -> [['f']]
(l:ls) -> ('f':l):ls
- > lines "\no"
lines ('\n':"o") = "": lines "o"
- > lines "o"
lines ('o':"") = case lines "" of
[] -> [['o']]
(l:ls) -> ('o':l):ls
- > lines ""
lines "" = []
- >返回[]
lines ('o':"") = case [] of
[] -> [['o']]
lines ('o':"") = [['o']]
- >返回["o"]
lines ('\n':cs) = "": ["o"]
- >返回"": ["o"]
lines ('f':"\no") = case "":["o"] of
(l:ls) -> ('f':l):ls
lines ('f':"\no") = ('f':""):["o"]
= ["f", "o"]
是吗?
答案 0 :(得分:2)
我试图在没有阅读你的解决方案的情况下解决这个问题。当我一半的时候,我头疼并开始进一步阅读你的帖子。据我所知,一切都与你所写的一致。剩下的部分很好地解释了你。
从我所知道的并回答你的问题,是的,你是对的。
答案 1 :(得分:2)
我建议您在代码中使用Debug.Trace.trace来跟踪调用并返回值:
trace :: String -> a -> a
例如:
import Debug.Trace
traceL l t v = trace (replicate l ' '++t) v
lines' :: String -> Int -> [String]
lines' "" l = traceL l"lines \"\" = " $ traceL l "[]" []
lines' ('\n':cs) l =
let v = (traceL l ("lines ('\\n':"++show cs++") = ") ""):lines' cs (l+1)
in (traceL l (show v) v)
lines' (c:cs) l =
let v = case traceL l ("lines ("++show c++":"++show cs++") = ") $ lines' cs (l+1) of [] -> [[c]];(x:xs) -> (c:x):xs
in (traceL l (show v) v)
l参数是调用级别。 希望它会有所帮助
答案 2 :(得分:1)
nu,对lines
的递归调用将堆叠,因此表达式将从右向左处理,将参数返回到先前的调用。类似的东西:
"o" will pass a "" as cs returning a []
'o' will then become ["o"] returning a (l:ls)
"\n" will become a "", cons'd into the ["o"], returning ["","o"], another (l:ls)
'f' will finally become the c in (c:l):ls meaning ('f':""):["o"] producing ["f","o"]