Haskell 哈斯克尔:方程扩展器1+;(1+;(1+;(1+;(…;))=∞;
Haskell是否存在方程扩展器 类似于:Haskell 哈斯克尔:方程扩展器1+;(1+;(1+;(1+;(…;))=∞;,haskell,expression,equation,expansion,equational-reasoning,Haskell,Expression,Equation,Expansion,Equational Reasoning,Haskell是否存在方程扩展器 类似于:1+(1+(1+(1+)(1+(…))=∞ 我是哈斯克尔的新手,我很难理解为什么某些方程比其他方程更可取。我想如果我能看到方程展开会有帮助 foldr :: (a -> b -> b) -> b -> [a] -> b foldr k z xs = go xs where go [] = z go (y:ys) = y `k` go
1+(1+(1+(1+)(1+(…))=∞代码>
我是哈斯克尔的新手,我很难理解为什么某些方程比其他方程更可取。我想如果我能看到方程展开会有帮助
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
例如,我发现foldr
vsfoldl
起初很难理解,直到我看到它们被扩展
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
从定义中,我可以看到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])))) -->
foldl (+) 0 [1..1000000] -->
foldl (+) (foldl (+) 0 [1]) [2..1000000]) -->
foldl (+) (foldl (+) (foldl (+) 0 [1])) [3..1000000]) -->
而foldl
的扩展如下:
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])))) -->
foldl (+) 0 [1..1000000] -->
foldl (+) (foldl (+) 0 [1]) [2..1000000]) -->
foldl (+) (foldl (+) (foldl (+) 0 [1])) [3..1000000]) -->
或来自:
然而,我很难理解为什么事情会像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
primes=sieve[2..]
哪里
sieve(p:xs)=p:sieve[x | x这绝不是对你问题的完整回答,但我在Haskell Cafe上发现了一段对话,其中有一些回答:
该线程链接到此包:
根据页面“允许您将重载表达式呈现为其文本表示形式”
提供的示例是:
*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))"
David V.感谢您提供这些链接。Repr
绝对值得添加到我的工具箱中。我想添加一些我觉得有用的附加库
(截至2010年12月12日)
- ghc事件库和程序:用于解析来自ghc的.eventlog文件的库和工具
- hood library:通过就地观察进行调试
- hpc选通库:hpc为正在运行的Haskell程序生成的选通
- hpc跟踪程序:带有AJAX接口的跟踪程序
钩包似乎是我要找的。今天晚些时候我会发布更多的样品
main = runO ex9
ex9 = print $ observe "foldl (+) 0 [1..4]" foldl (+) 0 [1..4]
输出
10
-- foldl (+) 0 [1..4]
{ \ { \ 0 1 -> 1
, \ 1 2 -> 3
, \ 3 3 -> 6
, \ 6 4 -> 10
} 0 (1 : 2 : 3 : 4 : [])
-> 10
}
我不知道Hackage库(因为我刚刚进入Haskell)。它让我想起了Perl的CPAN。感谢您提供这些链接。这是一个很好的资源。这是一个未问问题的答案,请将其视为一条长评论。
(如果您认为不合适,请在0以下进行向下投票。然后我将删除它。)
一旦你有了更多的经验,你可能就不想再看到事物扩展的方式了。你会想了解事物是如何工作的,而这将取代它为什么会工作的问题;仅仅通过观察事物是如何扩展的,你将不会再获得太多
分析代码的方法比您想象的要简单得多:只需根据因果关系的进展,将每个参数/变量标记为“已评估”或“未评估”或“待评估”
两个例子:
1.fibs
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
所有斐波那契数的列表如下
fibs :: (Num a) => [a]
fibs = 1 : 1 : zipWith (+) fibs (tail fibs)
前两个元素已经求值;因此,将第三个元素(值为2)标记为要求值,其余所有元素都标记为未求值。第三个元素将是(+)-fibs的第一个元素和尾部fibs的组合,这将是fibs的第一个和第二个元素,已标记为已评估元素。这分别适用于待评估的第n个元素和(n-2)-nd和(n-1)-st已评估元素
您可以通过不同的方式对此进行可视化,即:
fibs!!(i+0)
+ fibs!!(i+1)
= fibs!!(i+2)
(fibs)
zipWith(+) (tail fibs)
= (drop 2 fibs)
1 : 1 : 2 : 3 ...
(1 :)1 : 2 : 3 : 5 ...
(1 : 1 :)2 : 3 : 5 : 8 ...
2.)您的示例“筛(p:ps)xs”
我已经描述了它的功能(没有分析)
要训练这种类型的分析,您可能需要阅读一些标准库的源代码;例如,of中的scanl、scanr、Unfover。我想我记得在haskell cafe邮件列表中,您几乎想要的东西。我想它涉及一个带有特殊num实例的新类型,但我的记忆很模糊,我不确定我能找到它函数(.:)是什么意思?(.:)是一个类型为(a->b->b)的参数。如果将(.:)替换为f,则必须将.:替换为“f”。