Haskell 哈斯克尔:方程扩展器1+;(1+;(1+;(1+;(…;))=∞;

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

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 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
vs
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
从定义中,我可以看到
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”。