小编ylz*_*ang的帖子

使用foldr编写foldl

Real World Haskell中,第4章.函数式编程

用foldr写foldl:

-- file: ch04/Fold.hs
myFoldl :: (a -> b -> a) -> a -> [b] -> a

myFoldl f z xs = foldr step id xs z
    where step x g a = g (f a x)
Run Code Online (Sandbox Code Playgroud)

上面的代码让我很困惑,有人打电话给dps用一个有意义的名字重写它,使它更清晰:

myFoldl stepL zeroL xs = (foldr stepR id xs) zeroL
where stepR lastL accR accInitL = accR (stepL accInitL lastL)
Run Code Online (Sandbox Code Playgroud)

其他人,Jef G,通过提供一个例子并逐步展示基础机制,做得非常出色:

myFoldl (+) 0 [1, 2, 3]
= (foldR step id [1, 2, …
Run Code Online (Sandbox Code Playgroud)

recursion haskell fold

73
推荐指数
4
解决办法
1万
查看次数

(++)运算符和(:)运算符以及惰性求值

RealWorldHaskell的第8章

globToRegex' (c:cs) = escape c ++ globToRegex' cs
Run Code Online (Sandbox Code Playgroud)

这个函数不是尾递归的,它说答案依赖于Haskell非严格(懒惰)评估策略.该(++)运营商的简单定义在于以下这不是尾递归.

(++) :: [a] -> [a] -> [a]

(x:xs) ++ ys = x : (xs ++ ys)
[]     ++ ys = ys
Run Code Online (Sandbox Code Playgroud)

在严格的语言中,如果我们评估"foo" ++ "bar",则构造整个列表,然后返回.非严格评估在需要之前将大部分工作推迟.

如果我们要求表达式的元素,"foo" ++ "bar"函数定义的第一个模式匹配,我们返回表达式x : (xs ++ ys).因为(:)构造函数是非严格的,所以xs ++ ys可以推迟评估:我们生成更多的结果元素,无论它们需要什么速率.当我们生成更多结果时,我们将不再使用x,因此垃圾收集器可以回收它.由于我们按需生成结果元素,并且不保留我们完成的部分,因此编译器可以在恒定空间中评估我们的代码.

(重点补充.)

上面粗体的解释对Haskell来说是必不可少的,但是

  1. 我们怎么能理解呢?
  2. 底层发生了什么?
  3. " x:(xs ++ ys)会在恒定的空间中评估",怎么样?这听起来像尾递归一样!

haskell lazy-evaluation

6
推荐指数
3
解决办法
308
查看次数

如何移动到Emacs中的第一个单词?

例如,在Vim中,^可以将光标移动到该行的第一个单词(非空白空间)

    The quick brown fox jumps over the lazy dog

这里^的Vim将移动到T的The,但是在Emacs中,如何将光标移动到该行的第一个单词(非空白空间)而不是使用一系列Mb/f和Ca/e/b/f?是否有现成的命令来制作它?

谢谢

emacs

4
推荐指数
1
解决办法
716
查看次数

标签 统计

haskell ×2

emacs ×1

fold ×1

lazy-evaluation ×1

recursion ×1