13 haskell expression equation expansion equational-reasoning
是否存在Haskell的方程扩展器?
像foldr.com这样的东西:1+(1+(1+(1+(…))))=?
我是Haskell的新手我很难理解为什么某些方程比其他方程更优选.我认为如果我能看到方程扩展会有所帮助.
例如,我发现foldrvs foldl起初很难理解,直到我看到它们扩展.
foldr :: (a -> b -> b) -> b -> [a] -> b
foldr k z xs = go xs
where
go [] = z
go (y:ys) = y `k` go ys
foldl :: (a -> b -> a) -> a -> [b] -> a
foldl f z0 xs0 = lgo z0 xs0
where
lgo z [] = z
lgo z (x:xs) = lgo (f z x) xs
Run Code Online (Sandbox Code Playgroud)
根据定义,我可以看到foldr扩展如下:
foldr (+) 0 [1..1000000] -->
1 + (foldr (+) 0 [2..1000000]) -->
1 + (2 + (foldr (+) 0 [3..1000000])) -->
1 + (2 + (3 + (foldr (+) 0 [4..1000000]))) -->
1 + (2 + (3 + (4 + (foldr (+) 0 [5..1000000])))) -->
Run Code Online (Sandbox Code Playgroud)
并foldl像这样扩展:
foldl (+) 0 [1..1000000] -->
foldl (+) (foldl (+) 0 [1]) [2..1000000]) -->
foldl (+) (foldl (+) (foldl (+) 0 [1])) [3..1000000]) -->
Run Code Online (Sandbox Code Playgroud)
或者来自Haskell Wiki的foldr fold foldl':
let z1 = 0 + 1
in foldl (+) z1 [2..1000000] -->
let z1 = 0 + 1
z2 = z1 + 2
in foldl (+) z2 [3..1000000] -->
let z1 = 0 + 1
z2 = z1 + 2
z3 = z2 + 3
in foldl (+) z3 [4..1000000] -->
let z1 = 0 + 1
z2 = z1 + 2
z3 = z2 + 3
z4 = z3 + 4
in foldl (+) z4 [5..1000000] -->
Run Code Online (Sandbox Code Playgroud)
但是,我在更大的方程式上遇到麻烦,理解为什么事情就像他们在Haskell中那样工作.例如,第一筛选功能使用1000个过滤器,而第二筛功能仅需24个以找到1001个过滤器.
primes = sieve [2..]
where
sieve (p:xs) = p : sieve [x | x <- xs, rem x p /= 0]
primes = 2: 3: sieve (tail primes) [5,7..]
where
sieve (p:ps) xs = h ++ sieve ps [x | x <- t, rem x p /= 0]
-- or: filter ((/=0).(`rem`p)) t
where (h,~(_:t)) = span (< p*p) xs
Run Code Online (Sandbox Code Playgroud)
我花了很长时间锻炼并手工扩展.我已经了解它是如何工作的.但是,扩展某些表达式的自动化工具将极大地提高我对Haskell的理解.
此外,我认为它还可以帮助寻求优化Haskell代码的问题:
有没有扩展Haskell表达式的工具?
这绝不是对你问题的完整答复,但我在 Haskell-Cafe 上发现了一段对话,其中有一些答复:
http://www.haskell.org/pipermail/haskell-cafe/2010-June/078763.html
该线程链接到这个包:
http://hackage.haskell.org/package/repr根据页面“允许您将重载表达式渲染为其文本表示形式”
提供的示例是:
*Repr> let rd = 1.5 + 2 + (3 + (-4) * (5 - pi / sqrt 6)) :: Repr Double
*Repr> show rd
"fromRational (3 % 2) + 2 + (3 + negate 4 * (5 - pi / sqrt 6))"
Run Code Online (Sandbox Code Playgroud)