{"id":824,"date":"2009-11-13T15:47:35","date_gmt":"2009-11-13T15:47:35","guid":{"rendered":"http:\/\/scientopia.org\/blogs\/goodmath\/2009\/11\/13\/writing-basic-functions-in-haskell-edited-repost\/"},"modified":"2009-11-13T15:47:35","modified_gmt":"2009-11-13T15:47:35","slug":"writing-basic-functions-in-haskell-edited-repost","status":"publish","type":"post","link":"http:\/\/www.goodmath.org\/blog\/2009\/11\/13\/writing-basic-functions-in-haskell-edited-repost\/","title":{"rendered":"Writing Basic Functions in Haskell (edited repost)"},"content":{"rendered":"<p><em>(This is a heavily edited repost of the first article in my original<br \/>\nHaskell tutorial.)<\/em><\/p>\n<p><em>(I&#8217;ve attempted o write this as a literate haskell program. What that<br \/>\nmeans is that if you just cut-and-paste the text of this post from your<br \/>\nbrowser into a file whose name ends with &#8220;.lhs&#8221;, you should be able to run it<br \/>\nthrough a Haskell compiler: only lines that start with &#8220;&gt;&#8221; are treated as<br \/>\ncode. The nice thing about this is that this blog post is itself a<br \/>\ncompilable, loadable Haskell source file &#8211; so I&#8217;ve compiled and tested<br \/>\nall of the code in here in exactly this context.)<\/em><\/p>\n<p><!--more--><\/p>\n<p> Haskell is a functional programming language. At the simplest<br \/>\nlevel, what that means is that you write programs by writing functions &#8211; and the<br \/>\nfunctions are truly mathematical functions: they take a set of inputs, and generate<br \/>\na set of outputs, and the result of the function call is dependent solely<br \/>\non the values of the inputs. So, the best way to start out<br \/>\nlooking at Haskell is to look at how to write basic functions.<\/p>\n<p> So let&#8217;s dive right in a take a look at a very simple Haskell definition<br \/>\nof the factorial function:<\/p>\n<pre>\n&gt; simplest_fact n = if n == 0\n&gt;     then 1\n&gt;     else n * simplest_fact (n - 1)\n<\/pre>\n<p> This is the classic implementation of the factorial. Some things to<br \/>\nnotice:<\/p>\n<ol>\n<li> In Haskell, a function definition uses no keywords. Just &#8220;<code>name<br \/>\nparams = impl<\/code>&#8220;<\/li>\n<li> Function application is written by putting<br \/>\nthings side by side. So to apply the factorial function to <code>x<\/code>, we<br \/>\njust write <code>simplest_fact x<\/code>. Parens are only used for managing precedence.<br \/>\nThe parens in &#8220;<code>fsimplest_act (n - 1)<\/code>&#8221; aren&#8217;t there because the function<br \/>\nparameters need to be wrapped in parens, but because otherwise, the default<br \/>\nprecedence rules would parse it as &#8220;<code>(simplest_fact n) - 1<\/code>&#8220;.<\/li>\n<li> Haskell uses infix<br \/>\nsyntax for most mathematical operations. That doesn&#8217;t mean that they&#8217;re<br \/>\nspecial: they&#8217;re just an alternative way of writing a binary function<br \/>\ninvocation. You can define your own mathematical operators using normal<br \/>\nfuncion definitions.<\/li>\n<li> There are no explicit grouping constructs in Haskell:<br \/>\nno &#8220;{\/}&#8221;, no &#8220;begin\/end&#8221;. Haskell&#8217;s formal syntax uses braces, but the<br \/>\nlanguage defines how to translate indentation changes into braces; in<br \/>\npractice, just indenting the code takes care of grouping.\n<\/li>\n<\/ol>\n<p> That implementation of factorial, while correct, is not how most Haskell<br \/>\nprogrammers would normally implement it. Haskell includes a feature called<br \/>\n<em>pattern matching<\/em>, and most programmers would use pattern matching<br \/>\nrather than the <code>if\/then<\/code> statement for a case like that. Pattern matching<br \/>\nseparates things and often makes them easier to read. The basic idea of<br \/>\npattern matching in function definitions is that you can write what <em>look<br \/>\nlike<\/em> multiple versions of the function, each of which uses a different set of<br \/>\npatterns for its parameters (we&#8217;ll talk more about what patterns look like in<br \/>\ndetail in a later post); the different cases are separated not just by<br \/>\nsomething like a conditional statement, but they&#8217;re completely separated at<br \/>\nthe definition level. The case that matches the values at the point of call is<br \/>\nthe one that is actually invoked. So here&#8217;s a more stylistically correct<br \/>\nversion of the factorial:<\/p>\n<pre>\n&gt; pattern_fact 0 = 1\n&gt; pattern_fact n = n * pattern_fact (n - 1)\n&gt;\n<\/pre>\n<p> In the semantics of Haskell, those two are completely equivalent. In fact,<br \/>\nthe deep semantics of Haskell are based on pattern matching &#8211; so it&#8217;s more<br \/>\ncorrect to say that the if\/then\/else version is translated into the pattern<br \/>\nmatching version than vice-versa! At a low level, both will basically be<br \/>\nexpanded to the Haskell pattern-matching primitive called the<br \/>\n&#8220;<code>case<\/code>&#8221; statement, which selects from among a list of patterns:\n<\/p>\n<pre>\n&gt; cfact n = case n of\n&gt;              0 -&gt; 1\n&gt;              _ -&gt; n * cfact (n - 1)\n<\/pre>\n<p> Another way of writing the same thing is to use Haskell&#8217;s list type. Lists<br \/>\nare a very fundamental type in Haskell. They&#8217;re similar to lists in Lisp,<br \/>\nexcept that all of the elements of a list must have the same type. A list is<br \/>\nwritten between square brackets, with the values in the list written inside,<br \/>\nseparated by commas, like:<\/p>\n<pre>\n[1, 2, 3, 4, 5]\n<\/pre>\n<p> As in lisp, the list is actually formed from pairs, where the first<br \/>\nelement of the pair is a value in the list, and the second value is the rest<br \/>\nof the list. Pairs are <em>constructed<\/em> in Haskell using &#8220;<code>:<\/code>&#8220;,<br \/>\nso the list could also be written in the following ways:<\/p>\n<pre>\n1 : [2, 3, 4, 5]\n1 : 2 : [3, 4, 5]\n1 : 2 : 3 : 4 : 5 : []\n<\/pre>\n<p> If you want a list of integers in a specific range, there&#8217;s a shorthand<br \/>\nfor it using &#8220;<code>..<\/code>&#8220;. To generate the list of values from<br \/>\n<code>x<\/code> to <code>y<\/code>, you can write:<\/p>\n<pre>\n[ x .. y ]\n<\/pre>\n<p> Getting back to our factorial function, the factorial of a number &#8220;n&#8221; is<br \/>\nthe product of all of the integers from 1 to n. So another way of saying that<br \/>\nis that the factorial is the result of taking the list of all integers from 1<br \/>\nto n, and multiplying them together:<\/p>\n<pre>\nlistfact n = listProduct [1 .. n]\n<\/pre>\n<p> But that doesn&#8217;t work, because we haven&#8217;t defined <code>listProduct<\/code><br \/>\nyet. Fortunately, Haskell provides a ton of useful list functions. One of the<br \/>\nuseful types of list operations is <em>fold<\/em>, which comes in two versions:<br \/>\n<code>foldl<\/code> and <code>foldr<\/code>. What folds do is iterate over a<br \/>\nlist using some functions to combine elements. It takes a function to merge<br \/>\ntwo values, and an initial value for the merge. Then it takes the first<br \/>\nelement in the list, and merges it with the initial value of the result. Then<br \/>\nit takes the second value, and merges it with the result of the first. And so<br \/>\non.<\/p>\n<p> The difference between <code>foldl<\/code> and <code>foldr<\/code><br \/>\nis the associative order in which they do things: <code>foldl<\/code> starts<br \/>\nfrom the left, and foldr starts from the right.<\/p>\n<p> To illustrate, suppose we had a list <code>[1, 2, 3, 4, 5, 6]<\/code>. If<br \/>\nwe did <code>foldl (*) 1 [1, 2, 3, 4, 5, 6]<\/code>, it would evaluate as<br \/>\n&#8220;(((((1 * 1) * 2) * 3) * 4) * 5) * 6&#8221;. That is, it would start with 1, and<br \/>\nthen 2, and then 3, and so on. <code>foldr<\/code> would group<br \/>\nright-associative; it would do &#8220;1*(2*(3*(4*(5*(6*1)))))&#8221;. Since <code>*<\/code><br \/>\nis associative, the result value doesn&#8217;t matter. But it can make a significant<br \/>\ndifference in performance; the way that the Haskell ends up evaluating<br \/>\nfunction calls, you can easily wind up with programs where <code>foldr<\/code><br \/>\ncan be much faster that <code>foldl<\/code>.<\/p>\n<p> So, using fold, you can write the factorial using lists:<\/p>\n<pre>\n&gt; listfact n = listProduct [ 1 .. n ]\n&gt;        where listProduct lst = foldl (*) 1 lst\n<\/pre>\n<p> One thing that some Haskell programmers like to do is to write<br \/>\nwhat they call <em>points-free<\/em> functions: that is, functions<br \/>\nthat do not need to name any of their parameters. You can do an amazing<br \/>\namount of stuff in points-free Haskell. Personally, I&#8217;m not a fan of<br \/>\npoints-free programming: I find it much harder to read. But some people<br \/>\nlove it.<\/p>\n<p> To go points-free, you define a function in terms<br \/>\nof series of compositions of other functions. The elements of<br \/>\nthose compositions take care of pushing the values around to<br \/>\nget them to the right place. For factorial, it&#8217;s pretty easy. There&#8217;s<br \/>\na function called &#8220;<code>enumFromTo<\/code>&#8220;, which takes two<br \/>\nparameters, m and n, and generates a list of the values from m to n. Through<br \/>\na haskell feature called currying, if you take a two-parameter<br \/>\nfunction and only give it one parameter, you get back a one-parameter<br \/>\nfunction. So:<\/p>\n<pre>\n&gt; enumFromOne = enumFromTo 1\n<\/pre>\n<p> is exactly the same as:<\/p>\n<pre>\nenumFromOne n = enumFromTo 1 n\n<\/pre>\n<p> There&#8217;s a list function, &#8220;<code>product<\/code>&#8221; which takes the product of<br \/>\nall of the elements of a list &#8211; it&#8217;s basically a shorthand for &#8220;<code>zipwith<br \/>\n(*) 1<\/code>&#8220;. Finally, if you&#8217;ve got two functions f and g, you can<br \/>\nwrite the composition of the two functions as <code>g . f<\/code>. So,<br \/>\nto write a points-free factorial function, you could just write:<\/p>\n<pre>\n&gt; pointsfree_fact = product . (enumFromTo 1)\n<\/pre>\n<p> I need to explain one more list function before moving on. There&#8217;s a<br \/>\nfunction called &#8220;<code>zipWith<\/code>&gt;&#8221; for performing an operation pairwise<br \/>\non two lists. For example, given the lists &#8220;<code>[1,2,3,4,5]<\/code>&#8221; and<br \/>\n&#8220;<code>[2,4,6,8,10]<\/code>&#8220;, &#8220;<code>zipWith (+) [1,2,3,4,5]<br \/>\n[2,4,6,8,10]<\/code>&#8221; would result in &#8220;<code>[3,6,9,12,15]<\/code>&#8220;.<\/p>\n<p> Now we&#8217;re going to jump into something that&#8217;s going to seem really<br \/>\nstrange. One of the fundamental properties of how Haskell runs a program is<br \/>\nthat Haskell is a <em>lazy<\/em> language. What that means is that no<br \/>\nexpression is actually evaluated until its value is <em>needed<\/em>. So you<br \/>\ncan do things like create <em>infinite<\/em> lists &#8211; since no part of the list is<br \/>\ncomputed until it&#8217;s needed, you can create something that defines an infinite<br \/>\nlist &#8211; but since you&#8217;ll never access more than a finite number of elements of<br \/>\nit, it&#8217;s no problem. Using that, we can do some really clever things, like<br \/>\ndefine the complete series of fibonnaci numbers:<\/p>\n<pre>\n&gt; fiblist = 0 : 1 : (zipWith (+) fiblist (tail fiblist))\n<\/pre>\n<p>This looks very strange if you&#8217;re not used to it. But if we tease it apart a<br \/>\nbit, it&#8217;s really pretty simple:<\/p>\n<ol>\n<li> The first element of the fibonacci series is &#8220;0&#8221;.<\/li>\n<li> The second element of the fibonacci series is &#8220;1&#8221;.<\/li>\n<li> For the rest of the series, take the full fibonacci list, and<br \/>\nline up the two copies of it, offset by one (the full list, and the<br \/>\nlist without the first element), and add the values pairwise. <\/li>\n<\/ol>\n<p> That third step is the tricky one. It relies on the laziness of Haskell:<br \/>\nHaskell won&#8217;t compute the <em>nth<\/em> element of the list until you<br \/>\n<em>explicitly<\/em> reference it; until then, it just keeps around the<br \/>\n<em>unevaluated<\/em> code for computing the part of the list you haven&#8217;t<br \/>\nlooked at. So when you try to look at the <em>n<\/em>th value, it will compute<br \/>\nthe list <em>only up to<\/em> the <em>n<\/em>th value. So the actual computed<br \/>\npart of the list is always finite &#8211; but you can act as if it wasn&#8217;t. You can<br \/>\ntreat that list <em>as if<\/em> it really were infinite &#8211; and retrieve any<br \/>\nvalue from it that you want. Once it&#8217;s been referenced, then the list up to<br \/>\nwhere you looked is concrete &#8211; the computations <em>won&#8217;t<\/em> be repeated.<br \/>\nBut the last tail of the list will always be an unevaluated expression that<br \/>\ngenerates the <em>next<\/em> pair of the list &#8211; and <em>that<\/em> pair will<br \/>\nalways be the next element of the list, and an evaluated expression for the<br \/>\npair after it.<\/p>\n<p> Just to make sure that the way that &#8220;<code>zipWith<\/code>&#8221; is working in<br \/>\n&#8220;<code>fiblist<\/code>&#8221; is clear, let&#8217;s look at a prefix of the parameters to<br \/>\n<code>zipWith<\/code>, and the result. (Remember that those three are all actually the<br \/>\nsame list! The diagonals from bottom left moving up and right are the same<br \/>\nlist elements.)<\/p>\n<pre>\nfiblist      = [0  1  1  2  3  5  8 ...]\ntail fiblist = [1  1  2  3  5  8  ...  ]\nzipWith (+)  = [1  2  3  5  8  13 ...  ]\n<\/pre>\n<p>Given that list, we can find the <em>n<\/em>th element of the list very<br \/>\neasily; the <em>n<\/em>th element of a list <em>l<\/em> can be retrieved with<br \/>\n&#8220;<code>l !! n<\/code>&#8220;, so, the fibonacci function to get the <em>n<\/em>th<br \/>\nfibonacci number would be:<\/p>\n<pre>\n&gt; list_fib n = fiblist !! n\n<\/pre>\n<p> And using a very similar trick, we can do factorials the same way:<\/p>\n<pre>\n&gt; factlist = 1 : (zipWith (*) [1..] factlist)\n&gt; factl n = factlist !! n\n<\/pre>\n<p> The nice thing about doing factorial this way is that the values of all of<br \/>\nthe factorials <em>less than<\/em> n are also computed and remembered, so the<br \/>\nnext time you take a factorial, you don&#8217;t need to repeat those<br \/>\nmultiplications.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>(This is a heavily edited repost of the first article in my original Haskell tutorial.) (I&#8217;ve attempted o write this as a literate haskell program. What that means is that if you just cut-and-paste the text of this post from your browser into a file whose name ends with &#8220;.lhs&#8221;, you should be able to [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"jetpack_post_was_ever_published":false,"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_memberships_contains_paid_content":false,"footnotes":"","jetpack_publicize_message":"","jetpack_publicize_feature_enabled":true,"jetpack_social_post_already_shared":false,"jetpack_social_options":{"image_generator_settings":{"template":"highway","default_image_id":0,"font":"","enabled":false},"version":2}},"categories":[89],"tags":[],"class_list":["post-824","post","type-post","status-publish","format-standard","hentry","category-haskell"],"jetpack_publicize_connections":[],"jetpack_featured_media_url":"","jetpack_shortlink":"https:\/\/wp.me\/p4lzZS-di","jetpack_sharing_enabled":true,"jetpack_likes_enabled":true,"_links":{"self":[{"href":"http:\/\/www.goodmath.org\/blog\/wp-json\/wp\/v2\/posts\/824","targetHints":{"allow":["GET"]}}],"collection":[{"href":"http:\/\/www.goodmath.org\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/www.goodmath.org\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/www.goodmath.org\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"http:\/\/www.goodmath.org\/blog\/wp-json\/wp\/v2\/comments?post=824"}],"version-history":[{"count":0,"href":"http:\/\/www.goodmath.org\/blog\/wp-json\/wp\/v2\/posts\/824\/revisions"}],"wp:attachment":[{"href":"http:\/\/www.goodmath.org\/blog\/wp-json\/wp\/v2\/media?parent=824"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/www.goodmath.org\/blog\/wp-json\/wp\/v2\/categories?post=824"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/www.goodmath.org\/blog\/wp-json\/wp\/v2\/tags?post=824"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}