{"id":35,"date":"2007-06-14T10:21:06","date_gmt":"2007-06-14T18:21:06","guid":{"rendered":"http:\/\/evanlenz.net\/blog\/2007\/06\/14\/generalizing-recursion-on-integers\/"},"modified":"2007-06-14T10:21:51","modified_gmt":"2007-06-14T18:21:51","slug":"generalizing-recursion-on-integers","status":"publish","type":"post","link":"https:\/\/evanlenz.net\/blog\/2007\/06\/14\/generalizing-recursion-on-integers\/","title":{"rendered":"Generalizing recursion on integers"},"content":{"rendered":"<p>I thought I&#8217;d post a brief answer to the question I raised in my last post, which was &#8220;is there an analogous higher-order function [like <em>foldr<\/em>] for recursion on numbers?&#8221;<\/p>\n<p>As I pointed out, you can define <em>product<\/em> using foldr, like this:<\/p>\n<pre>product = foldr (*) 1<\/pre>\n<p>What I wanted is another function, say <em>foldrNum<\/em>, that would allow me to define <em>factorial<\/em> using the same idea:<\/p>\n<pre>factorial = foldrNum (*) 1<\/pre>\n<p>As it turns out, all I need to do is make some slight modifications to the foldr definition, which looks like this:<\/p>\n<pre>foldr            :: (a -> b -> b) -> b -> [a] -> b\r\nfoldr op v []     = v\r\nfoldr op v (x:xs) = op x (foldr op v xs)<\/pre>\n<p>I&#8217;ll keep foldrNum general enough so that, like foldr, it can return a value of any type (<code>b<\/code>), but unlike foldr, which can process a list of any type (<code>a<\/code>), I think it&#8217;s essential to the idea of foldrNum that it only operate on a non-negative integer, which is what the recursion is based on. First, I&#8217;ll show the definition of foldrNum I came up with. Then I&#8217;ll compare it line-by-line with foldr so that we can see exactly what&#8217;s the same and what&#8217;s different.<\/p>\n<p>Here&#8217;s foldrNum:<\/p>\n<pre>foldrNum           :: (Int -> b -> b) -> b -> Int -> b\r\nfoldrNum op v 0     = v\r\nfoldrNum op v (n+1) = op (n+1) (foldrNum op v n)<\/pre>\n<p>The similarities are obvious, but I like to make things as obvious as possible. First, the types of each function:<\/p>\n<pre>foldr               :: (<strong>a<\/strong>   -> b -> b) -> b -> <strong>[a]<\/strong> -> b\r\nfoldrNum            :: (<strong>Int<\/strong> -> b -> b) -> b -> <strong>Int<\/strong> -> b<\/pre>\n<p>Now, the base case:<\/p>\n<pre>foldr    op v <strong>[]<\/strong>     = v\r\nfoldrNum op v <strong>0<\/strong>      = v<\/pre>\n<p>Finally, the recursive case:<\/p>\n<pre>foldr    op v <strong>(x:xs)<\/strong> = op <strong>x<\/strong>     (foldr    op v <strong>xs<\/strong>)\r\nfoldrNum op v <strong>(n+1)<\/strong>  = op <strong>(n+1)<\/strong> (foldrNum op v <strong>n<\/strong>)<\/pre>\n<p>The natural question arising from this is &#8220;How do I generalize foldr and foldrNum, since they&#8217;re so much alike?&#8221; Joshua Ball anticipated that question in <a href=\"http:\/\/evanlenz.net\/blog\/2007\/06\/12\/learning-haskell\/#comment-41007\">his comment on my last post<\/a>, although I confess I haven&#8217;t fully wrapped my head around his solution yet.<\/p>\n<p>I think this is enough for today. So many possible directions to go in. I must content myself with one small piece at a time. \ud83d\ude42<\/p>\n","protected":false},"excerpt":{"rendered":"<p>I thought I&#8217;d post a brief answer to the question I raised in my last post, which was &#8220;is there an analogous higher-order function [like foldr] for recursion on numbers?&#8221; As I pointed out, you can define product using foldr, like this: product = foldr (*) 1 What I wanted is another function, say foldrNum, [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":[],"categories":[9],"tags":[],"_links":{"self":[{"href":"https:\/\/evanlenz.net\/blog\/wp-json\/wp\/v2\/posts\/35"}],"collection":[{"href":"https:\/\/evanlenz.net\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/evanlenz.net\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/evanlenz.net\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/evanlenz.net\/blog\/wp-json\/wp\/v2\/comments?post=35"}],"version-history":[{"count":0,"href":"https:\/\/evanlenz.net\/blog\/wp-json\/wp\/v2\/posts\/35\/revisions"}],"wp:attachment":[{"href":"https:\/\/evanlenz.net\/blog\/wp-json\/wp\/v2\/media?parent=35"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/evanlenz.net\/blog\/wp-json\/wp\/v2\/categories?post=35"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/evanlenz.net\/blog\/wp-json\/wp\/v2\/tags?post=35"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}