有人可以向我解释这些Haskell功能吗?

Ray*_*yne 2 recursion haskell functional-programming lazy-evaluation

我过去曾经涉足过Haskell,最近又认真地回到了它,我正在阅读真实的世界.他们已经发光的一些例子,我还没有理解.在这一个:

myLength []     = 0
myLength (x:xs) = 1 + myLength (xs)
Run Code Online (Sandbox Code Playgroud)

我不知道这是如何工作的,真正添加的是什么?递归如何返回可以添加的内容?我不明白.

在这里我们有这个:

splitLines [] = []
splitLines cs =
       let (pre, suf) = break isLineTerminator cs
       in  pre : case suf of 
                   ('\r':'\n':rest) -> splitLines rest
                   ('\r':rest)      -> splitLines rest
                   ('\n':rest)      -> splitLines rest
                   _                -> []

isLineTerminator c = c == '\r' || c == '\n'
Run Code Online (Sandbox Code Playgroud)

这是如何工作的,什么是真正的附加呢?我没有看到case表达式的结果是如何预先连接到的.也许我只需要有人详细解释这些功能的评估.我必须遗漏一些非常重要的东西.

提前致谢!

编辑:我知道,这是一个复制粘贴失败.抱歉.

编辑2:似乎我的困惑在于这些功能实际/返回/我现在已经解决了.谢谢你们的答案,终于点击了!我很感激!

wax*_*ing 10

至于第一个,它是一种非常基本的递归方式.但是,似乎缺少一部分:

myLength [] = 0
Run Code Online (Sandbox Code Playgroud)

它的工作原理是从列表中缩小一个元素并将一个元素添加到结果中.要想象,请考虑通话

myLength [1,2,3]
Run Code Online (Sandbox Code Playgroud)

将评估为:

1 + myLength [2,3]
1 + 1 + myLength [3]
1 + 1 + 1 + myLength []
1 + 1 + 1 + 0
Run Code Online (Sandbox Code Playgroud)

这是3.

至于第二个,嗯,你已经把下一个换行符的字符串分成两个部分:pre和suf.现在,suf将以\n,\n或\ r或\ r \n开头.我们想删除这些.所以我们使用模式匹配.看看rest变量本质上是suf变量减去初始换行符.

所以我们有pre,这是第一行,rest,这是文本的其余部分.因此,为了继续将休息分成行,我们以递归方式调用splitLines并将结果连接到pre.

要想象,请说你有字符串"foo \nbar\r \n \nbaz".

所以,在调用时,结果将是:

[ pre => foo, suf => \nbar\r\nbaz, rest => bar\r\n\baz ]
foo : splitLines bar\r\nbaz
Run Code Online (Sandbox Code Playgroud)

然后再次调用splitLines,结果扩展为:

[ pre => bar, suf => \r\nbaz, rest = baz ]
foo : bar : splitLines baz
Run Code Online (Sandbox Code Playgroud)

再一次:

[ pre => baz, suf => [], rest = [] ]
foo : bar : baz
Run Code Online (Sandbox Code Playgroud)

这是最后的结果.

  • 随着Haskell问题得到彻底和完全回答的速度,我认为你不需要道歉.你清楚地想到这一段时间,只是错过了一块.要求另一双眼睛指出你离开轨道的地方并不是一件坏事.我发现有一种技术对Haskell这样的混淆很有帮助,就是要仔细查看我没有得到的任何函数或表达式的类型签名.它在Haskell中比在我使用的任何其他语言中更有帮助. (2认同)