<html xmlns:v="urn:schemas-microsoft-com:vml" xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:w="urn:schemas-microsoft-com:office:word" xmlns:m="http://schemas.microsoft.com/office/2004/12/omml" xmlns="http://www.w3.org/TR/REC-html40">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<meta name="Generator" content="Microsoft Word 15 (filtered medium)">
<style><!--
/* Font Definitions */
@font-face
{font-family:"Cambria Math";
panose-1:2 4 5 3 5 4 6 3 2 4;}
@font-face
{font-family:Calibri;
panose-1:2 15 5 2 2 2 4 3 2 4;}
/* Style Definitions */
p.MsoNormal, li.MsoNormal, div.MsoNormal
{margin:0cm;
margin-bottom:.0001pt;
font-size:11.0pt;
font-family:"Calibri",sans-serif;
color:black;}
a:link, span.MsoHyperlink
{mso-style-priority:99;
color:blue;
text-decoration:underline;}
a:visited, span.MsoHyperlinkFollowed
{mso-style-priority:99;
color:purple;
text-decoration:underline;}
p.Code, li.Code, div.Code
{mso-style-name:Code;
margin-top:0cm;
margin-right:0cm;
margin-bottom:0cm;
margin-left:36.0pt;
margin-bottom:.0001pt;
font-size:9.0pt;
font-family:"Courier New";
color:black;}
p.msonormal0, li.msonormal0, div.msonormal0
{mso-style-name:msonormal;
mso-margin-top-alt:auto;
margin-right:0cm;
mso-margin-bottom-alt:auto;
margin-left:0cm;
font-size:11.0pt;
font-family:"Calibri",sans-serif;
color:black;}
span.EmailStyle19
{mso-style-type:personal-reply;
font-family:"Calibri",sans-serif;
color:windowtext;
font-weight:normal;
font-style:normal;
text-decoration:none none;}
.MsoChpDefault
{mso-style-type:export-only;
font-size:10.0pt;}
@page WordSection1
{size:612.0pt 792.0pt;
margin:72.0pt 72.0pt 72.0pt 72.0pt;}
div.WordSection1
{page:WordSection1;}
--></style><!--[if gte mso 9]><xml>
<o:shapedefaults v:ext="edit" spidmax="1026" />
</xml><![endif]--><!--[if gte mso 9]><xml>
<o:shapelayout v:ext="edit">
<o:idmap v:ext="edit" data="1" />
</o:shapelayout></xml><![endif]-->
</head>
<body bgcolor="white" lang="EN-GB" link="blue" vlink="purple">
<div class="WordSection1">
<p class="MsoNormal" style="margin-left:36.0pt">Also, languages are borrowing from each other at a rapid rate these days (eg Rust traits are equivalent to type classes) so it's hard to find a "killer feature" in Haskell any more<o:p></o:p></p>
<p class="MsoNormal"><span style="font-size:12.0pt;color:windowtext"><o:p> </o:p></span></p>
<p class="MsoNormal"><span style="font-size:12.0pt;color:windowtext">That’s true, and to be celebrated!<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:12.0pt;color:windowtext"><o:p> </o:p></span></p>
<p class="MsoNormal"><span style="font-size:12.0pt;color:windowtext">One thing that stands our for me is the ability to abstract over type
<b>constructors</b>:<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:12.0pt;color:windowtext"> f :: forall (m :: * -> *) (a :: *). Monad m => a -> m a<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:12.0pt;color:windowtext"><o:p> </o:p></span></p>
<p class="MsoNormal"><span style="font-size:12.0pt;color:windowtext">That ability is what has given rise to a stunningly huge collection of abstractions: not just Monad, but Functor, Applicative, Traversable, Foldable, etc etc etc. Really a lot. It opens
up a new way to think about the world. But only made possible by that one feature. (Plus type classes of course.)<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:12.0pt;color:windowtext"><o:p> </o:p></span></p>
<p class="MsoNormal"><span style="font-size:12.0pt;color:windowtext">Do any statically typed languages other than Haskell and Scala do this?<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:12.0pt;color:windowtext"><o:p> </o:p></span></p>
<p class="MsoNormal"><span style="font-size:12.0pt;color:windowtext">Simon<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:12.0pt;color:windowtext"><o:p> </o:p></span></p>
<div style="border:none;border-left:solid blue 1.5pt;padding:0cm 0cm 0cm 4.0pt">
<div>
<div style="border:none;border-top:solid #E1E1E1 1.0pt;padding:3.0pt 0cm 0cm 0cm">
<p class="MsoNormal"><b><span lang="EN-US" style="color:windowtext">From:</span></b><span lang="EN-US" style="color:windowtext"> Haskell-Cafe <haskell-cafe-bounces@haskell.org>
<b>On Behalf Of </b>Neil Mayhew<br>
<b>Sent:</b> 11 July 2018 17:12<br>
<b>To:</b> Haskell Cafe <haskell-cafe@haskell.org><br>
<b>Subject:</b> Re: [Haskell-cafe] What is your favourite Haskell "aha" moment?<o:p></o:p></span></p>
</div>
</div>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">I came to Haskell from C++, and I was used to the idea of parametric types and functions from C++ templates.<br>
<br>
However, what I really liked about Haskell's way of doing these was that, due to type inference, not only is there a lot less ceremony involved, but code is generic (parametric) *by default*, and thus much more reusable, although you still have the option of
tightening it up by adding a type annotation (eg for performance reasons). For a while, I was writing all my C++ code as templates, but this ended up being a pain.<br>
<br>
Also, traditionally C++ has not allowed you to place any constraints on template arguments (type parameters) whereas Haskell's type classes are a very elegant way of doing it. (C++ now has concepts, but I haven't taken the time yet to see how they compare with
type classes.)<br>
<br>
I was also used to function overloading, which is somewhat similar to type inference, in that the compiler will pick an implementation based on the types of a function's arguments. This is similar to Haskell picking an implementation from among type class instances.
However, what blew me away is that Haskell can overload based on *return type* as well as argument types. I haven't seen any other production-ready language that can do this. A great example of how this is useful is the regex library, where you can select
from among widely varying styles of regex matching result simply by type inference, ie without needing any type annotation.<br>
<br>
There were a *lot* of other things I found amazing, but others have covered many of these already. Also, languages are borrowing from each other at a rapid rate these days (eg Rust traits are equivalent to type classes) so it's hard to find a "killer feature"
in Haskell any more (except laziness, perhaps). I think it's more the well-balanced combination of all the features that makes Haskell so pleasant to work in, and it's hard to demonstrate all of these in a single example.<br>
<br>
My own favourite "gem" is this code for computing all primes, based on code in a paper[1] by Doug McIlroy:<br>
<br>
primes = sieve [2..] where sieve (p : ns) = p : sieve [n | n <- ns, n `mod` p /= 0]<br>
<br>
I think care must be exercised, when using examples like this one, to avoid giving the impression that Haskell is a "toy" language. However, what I find interesting about this example is that all other sieve implementations I've seen work on a fixed size of
sieve up front, and if you later change your mind about how many primes you want, eg because you're expanding a hash table and want a bigger prime for the size, you typically have to start the sieve from scratch again.<br>
<br>
[1]: <a href="https://na01.safelinks.protection.outlook.com/?url=http:%2F%2Fwww.cs.dartmouth.edu%2F~doug%2Fsieve%2Fsieve.pdf&data=02%7C01%7Csimonpj%40microsoft.com%7Cce59cb95fe304d442b8d08d5e7490739%7C72f988bf86f141af91ab2d7cd011db47%7C1%7C0%7C636669223196857658&sdata=1UGE8hoL8B9yMjXqJbe5HV%2FsAXlpoB653kePOrgpCNY%3D&reserved=0">
http://www.cs.dartmouth.edu/~doug/sieve/sieve.pdf</a><o:p></o:p></p>
</div>
</div>
</body>
</html>