{"id":228,"date":"2006-11-28T12:40:32","date_gmt":"2006-11-28T12:40:32","guid":{"rendered":"http:\/\/scientopia.org\/blogs\/goodmath\/2006\/11\/28\/simple-functions-in-haskell\/"},"modified":"2006-11-28T12:40:32","modified_gmt":"2006-11-28T12:40:32","slug":"simple-functions-in-haskell","status":"publish","type":"post","link":"http:\/\/www.goodmath.org\/blog\/2006\/11\/28\/simple-functions-in-haskell\/","title":{"rendered":"Simple Functions in Haskell"},"content":{"rendered":"<p>I wasn&#8217;t really sure of quite how to start this off. I finally decided to just dive right in with a simple function definition, and then give you a bit of a tour of how Haskell works by showing the different ways of implementing it.<\/p>\n<p><!--more--><br \/>\nSo let&#8217;s dive right in a take a look at a very simple Haskell definition of the factorial function:<br \/>\nfact n = if n == 0<br \/>\nthen 1<br \/>\nelse n * fact (n &#8211; 1)<br \/>\nThis is the classic implementation of the factorial. Some things to notice:<br \/>\n1. In Haskell, a function definition uses no keywords. Just &#8220;`name params = impl`&#8221;.<br \/>\n2. Function application is written by putting things side by side. So to apply<br \/>\nthe factorial function to `x`, we just write `fact x`. Parens are only used for<br \/>\nmanaging precedence. The parens in &#8220;`fact (n &#8211; 1)`&#8221; aren&#8217;t there because the<br \/>\nfunction parameters need to be wrapped in parens, but because otherwise,<br \/>\nthe default precedence rules would parse it as &#8220;`(fact n) &#8211; 1`&#8221;.<br \/>\n3. Haskell uses infix syntax for most mathematical operations. That doesn&#8217;t mean that<br \/>\nthey&#8217;re special: they&#8217;re just an alternative way of writing a binary function<br \/>\ninvocation. You can define your own mathematical operators using normal function<br \/>\ndefinitions.<br \/>\n4. There are no explicit grouping constructs in Haskell: no &#8220;{\/}&#8221;, no &#8220;begin\/end&#8221;. Haskell&#8217;s<br \/>\nformal syntax uses braces, but the language defines how to translate indentation changes<br \/>\ninto braces; in practice, just indenting the code takes care of grouping.<br \/>\nThat implementation of factorial, while correct, is not how most Haskell programmers would implement<br \/>\nit. Haskell includes a feature called <em>pattern matching<\/em>, and most programmers would use<br \/>\npattern matching rather than the `if\/then` statement for a case like that. Pattern matching separates<br \/>\nthings and often makes them easier to read. The basic idea of pattern matching in function<br \/>\ndefinitions is that you can write what *look like* multiple versions of the function, each of which<br \/>\nuses a different set of patterns 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 something like a conditional statement, but they&#8217;re completely separated at the definition level.   The case that matches the values at the point of call is the one that is actually invoked. So here&#8217;s a more stylistically correct version of the factorial:<br \/>\nfact 0 = 1<br \/>\nfact n = n * fact (n &#8211; 1)<br \/>\nIn the semantics of Haskell, those two are completely equivalent. In fact, the deep semantics of Haskell are based on pattern matching &#8211; so it&#8217;s more correct to say that the if\/then\/else version<br \/>\nis translated into the pattern matching version than vice-versa! In fact, both will basically expand to the Haskell pattern-matching primitive called the &#8220;`case`&#8221; statement, which selects from<br \/>\namong a list of patterns: *(Note: I originally screwed up the following, by putting a single &#8220;=&#8221; instead of a &#8220;==&#8221; inside the comparison. Stupid error, and since this was only written to explain things, I didn&#8217;t actually run it. Thanks to pseudonym for pointing out the error.)*<br \/>\nfact n = case (n==0) of<br \/>\nTrue -&gt; 1<br \/>\nFalse -&gt; n * fact (n &#8211; 1)<br \/>\nAnother way of writing the same thing is to use Haskell&#8217;s list type. Lists are a very fundamental type in Haskell. They&#8217;re similar to lists in Lisp, except that all of the elements of a list must have the same type. A list is written between square brackets, with the values in the list written<br \/>\ninside, separated by commas, like:<br \/>\n[1, 2, 3, 4, 5]<br \/>\nAs in lisp, the list is actually formed from pairs, where the first element of the pair is<br \/>\na value in the list, and the second value is the rest of the list. Pairs are *constructed* in Haskell using &#8220;`:`&#8221;, so the list could also be written in the following ways:<br \/>\n1 : [2, 3, 4, 5]<br \/>\n1 : 2 : [3, 4, 5]<br \/>\n1 : 2 : 3 : 4 : 5 : []<br \/>\nIf you want a list of integers in a specific range, there&#8217;s a shorthand for it using &#8220;`..`&#8221;. To generate the list of values from `x` to `y`, you can write:<br \/>\n[ x .. y ]<br \/>\nGetting back to our factorial function, the factorial of a number &#8220;n&#8221; is the product of all of the<br \/>\nintegers from 1 to n. So another way of saying that is that the factorial is the result of taking the list of all integers from 1 to n, and multiplying them together:<br \/>\nlistfact n = listProduct [1 .. n]<br \/>\nBut that doesn&#8217;t work, because we haven&#8217;t defined `listProduct` yet. Fortunately, Haskell provides<br \/>\na ton of useful list functions. One of them, &#8220;`foldl`&#8221;, takes a function *f*, an initial value *i*,<br \/>\nand a list *[l<sub>1<\/sub>, l<sub>2<\/sub>,&#8230;,l<sub>n<\/sub>]*, and basically does *f(l<sub>n<\/sub>(&#8230;f(l<sub>2<\/sub>, f(i,l<sub>1<\/sub>))))*. So we can use `foldl` with the multiply<br \/>\nfunction to multiply the elements of the list together. The only problem is that multiplication is written as an infix operator, not a function. In Haskell, the solution to *that* is simple: an infix operator is just fancy syntax for a function call; to get the function, you just put the operator<br \/>\ninto parens. So the multiplication *function* is written &#8220;`(*)`&#8221;. So let&#8217;s add a definition of `listProduct` using that; we&#8217;ll do it using a *`where`* clause, which allows us to define<br \/>\nvariables or functions that are local to the scope of the enclosing function definition:<br \/>\nlistfact n = listProduct [ 1 .. n ]<br \/>\nwhere listProduct lst = foldl (*) 1 lst<br \/>\nI need to explain one more list function before moving on. There&#8217;s a function called &#8220;`zipWith`&#8221; for performing an operation pairwise on two lists. For example, given the lists &#8220;`[1,2,3,4,5]`&#8221; and &#8220;`[2,4,6,8,10]`&#8221;, &#8220;`zipWith (+) [1,2,3,4,5] [2,4,6,8,10]`&#8221; would result in &#8220;`[3,6,9,12,15]`&#8221;.<br \/>\nNow we&#8217;re going to jump into something that&#8217;s going to seem really strange. One of the fundamental<br \/>\nproperties of how Haskell runs a program is that Haskell is a *lazy* language. What that means is<br \/>\nthat no expression is actually evaluated until its value is *needed*. So you can do things like<br \/>\ncreate *infinite* lists &#8211; since no part of the list is computed until it&#8217;s needed. So we can do<br \/>\nthings like define the fibonacci series &#8211; the *complete* fibonacci series, using:<br \/>\nfiblist = 0 : 1 : (zipWith (+) fiblist (tail fiblist))<br \/>\nThis looks incredibly strange. But if we tease it apart a bit, it&#8217;s really pretty simple:<br \/>\n1. The first element of the fibonacci series is &#8220;0&#8221;<br \/>\n2. The second element of the fibonacci series is &#8220;1&#8221;<br \/>\n3. For the rest of the series, take the full fibonacci list, and line up the two copies<br \/>\nof it, offset by one (the full list, and the list without the first element), and add the<br \/>\nvalues pairwise.<br \/>\nThat third step is the tricky one. It relies on the *laziness* of Haskell:<br \/>\nHaskell won&#8217;t compute the *nth* element of the list until you *explicitly*<br \/>\nreference it; until then, it just keeps around the *unevaluated* code for computing the part of the list you haven&#8217;t looked at. So when you try to look at the *n*th value, it will compute the list *only up to* the *n*th value. So the actual computed part of the list is always finite &#8211; but you can act as if it wasn&#8217;t. You can treat that list *as if* it really were infinite &#8211; and retrieve any value from it that you want. Once it&#8217;s been referenced, then the list up to where you looked is concrete &#8211; the computations *won&#8217;t* be repeated. But the last tail of the list will always be an<br \/>\nunevaluated expression that generates the *next* pair of the list &#8211; and *that* pair will always be the next element of the list, and an evaluated expression for the pair after it.<br \/>\nJust to make sure that the way that &#8220;`zipWith`&#8221; is working in &#8220;`fiblist`&#8221; is clear, let&#8217;s look<br \/>\nat a prefix of the parameters to `zipWith`, and the result. (Remember that those three are all<br \/>\nactually the same list! The diagonals from bottom left moving up and right are the same list elements.)<br \/>\nfiblist      = [0  1  1  2  3  5  8 &#8230;]<br \/>\ntail fiblist = [1  1  2  3  5  8  &#8230;  ]<br \/>\nzipWith (+)  = [1  2  3  5  8  13 &#8230;  ]<br \/>\nGiven that list, we can find the *n*th element of the list very easily; the *n*th element of a list *l* can be retrieved with &#8220;`l !! n`&#8221;, so, the fibonacci function to get the *n*th fibonacci<br \/>\nnumber would be:<br \/>\nfib n = fiblist !! n<br \/>\nAnd using a very similar trick, we can do factorials the same way:<br \/>\nfactlist = 1 : (zipWith (*) [1..] factlist)<br \/>\nfactl n = factlist !! n<br \/>\nThe nice thing about doing factorial this way is that the values of all of the factorials *less than* *n* are also computed and remember &#8211; so the next time you take a factorial, you don&#8217;t need to<br \/>\nrepeat those multiplications.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>I wasn&#8217;t really sure of quite how to start this off. I finally decided to just dive right in with a simple function definition, and then give you a bit of a tour of how Haskell works by showing the different ways of implementing it.<\/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-228","post","type-post","status-publish","format-standard","hentry","category-haskell"],"jetpack_publicize_connections":[],"jetpack_featured_media_url":"","jetpack_shortlink":"https:\/\/wp.me\/p4lzZS-3G","jetpack_sharing_enabled":true,"jetpack_likes_enabled":true,"_links":{"self":[{"href":"http:\/\/www.goodmath.org\/blog\/wp-json\/wp\/v2\/posts\/228","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=228"}],"version-history":[{"count":0,"href":"http:\/\/www.goodmath.org\/blog\/wp-json\/wp\/v2\/posts\/228\/revisions"}],"wp:attachment":[{"href":"http:\/\/www.goodmath.org\/blog\/wp-json\/wp\/v2\/media?parent=228"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/www.goodmath.org\/blog\/wp-json\/wp\/v2\/categories?post=228"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/www.goodmath.org\/blog\/wp-json\/wp\/v2\/tags?post=228"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}