-
Notifications
You must be signed in to change notification settings - Fork 1
/
index.html
1621 lines (1382 loc) · 83.2 KB
/
index.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
<!DOCTYPE HTML>
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8">
<title>Melbourne Haskell Workshop 2015</title>
<link href="resources/css/styles.css" rel="stylesheet" type="text/css">
<link href="resources/css/toc.css" rel="stylesheet" type="text/css">
<link href="resources/css/fonts.css" rel="stylesheet" type="text/css">
<link href="resources/css/solarized-light.css" rel="stylesheet" type="text/css">
</head>
<body class="">
<div id="content">
<div class='chapter'>
<div class='content'>
<h1 id="melbourne-haskell-workshop-2015">Melbourne Haskell Workshop 2015</h1>
<!-- Trickery to conditionally display the alternate format link -->
<h3 id="html-link" class="center"><a href="http://sordina.github.io/haskell_workshop/">(HTML)</a></h3>
<div class="important">
<script type="text/javascript">
document.getElementById('html-link').remove()
document.write("<h3 class='center'><a href='workshop.pdf'>(PDF)</a></h3>")
</script>
<pre class="note notitle"><code>Press "o" to toggle only showing the most important content
Press "t" to toggle showing the table of contents</code></pre>
</div>
<div class="center important">
<p>A single-day workshop intended to introduce Haskell to newcomers to functional-programming.</p>
</div>
<!-- https://www.flickr.com/photos/fatmandy/4221136071/in/photolist-7r1qG8-4Ew9ka-7GmuKi-7GH1pP-65YZoM-nGeWhj-7KAY7X-nS3L1Y-j1TkSn-8Ef3BW-6CHTcd-9QVtVW-oDN5ak-4BMnsd-cUC6HY-9QSD52-hseG5J-9vPTiH-CkmeT-bQZgze -->
<div class="center nopad">
<img src="resources/images/workshop.png" alt="Workshop" />
</div>
<p>Outcomes include...</p>
<ul>
<li>Creating, editing, running and interacting with Haskell programs</li>
<li>Building the confidence to solve problems in the wild with Haskell</li>
<li>Developing an understanding of the Haskell ecosystem</li>
<li>Interacting with others in a collaborative environment</li>
</ul>
<div class="important note">
<p>If you are attending the workshop, make sure that you RSVP via <a href="http://www.meetup.com/Melbourne-Haskell-Users-Group/events/219493786/">Meetup</a>. Please also attempt to have the required items from the <a href="#resources">'Resources'</a> section available for your use during the workshop.</p>
<p>If you would like to volunteer, please send an email to the <script type="text/javascript">
<!--
h='googlegroups.com';a='@';n='melb-haskell-workshop-organisers';e=n+a+h;
document.write('<a h'+'ref'+'="ma'+'ilto'+':'+e+'" clas'+'s="em' + 'ail">'+'mailing list'+'<\/'+'a'+'>');
// -->
</script><noscript>mailing list (melb-haskell-workshop-organisers at googlegroups dot com)</noscript>, or contact us via the meetup.</p>
<p>Workshop development is tracked on <a href="https://trello.com/b/c1jhkXh9/haskell-workshop-2015">Trello</a>.</p>
</div>
</div>
</div>
<div class='chapter'>
<div class='content'>
<hr />
<h1 id="table-of-contents">Table of Contents</h1>
<div id="toc" class="important">
<!-- Note: This is a special file that determines the order of the chapters -->
<!-- The lefthand column refers to the filename of the chapter in 'resources/markdown' -->
<!-- This column is removed before the markdown is processed for the table of contents -->
<!-- ';' is a comment -->
<table>
<tbody>
<tr class="odd">
<td align="left"><a href="#required-resources">Resources</a></td>
<td align="left">Resources Available and Required</td>
<td align="left">1m</td>
</tr>
<tr class="even">
<td align="left"><a href="#welcome">Welcome</a></td>
<td align="left">Motivation, Overview, and Approach</td>
<td align="left">15m</td>
</tr>
<tr class="odd">
<td align="left"><a href="#setup">Setup</a></td>
<td align="left">Setting up your Haskell environment</td>
<td align="left">15m</td>
</tr>
<tr class="even">
<td align="left"><a href="#introduction">Introduction</a></td>
<td align="left">Introductory Exercises</td>
<td align="left">30m</td>
</tr>
<tr class="odd">
<td align="left"><a href="#types">Types</a></td>
<td align="left">The Haskell Type System</td>
<td align="left">30m</td>
</tr>
<tr class="even">
<td align="left"><a href="#adts-algebraic-data-types">ADTs</a></td>
<td align="left">Modelling with data in Haskell</td>
<td align="left">1h</td>
</tr>
<tr class="odd">
<td align="left"><a href="#lunch-break">~ Lunch Break ~</a></td>
<td align="left">Nandos -> IO Nomnomnomnomnom</td>
<td align="left">1h</td>
</tr>
<tr class="even">
<td align="left"><a href="#laziness">Laziness</a></td>
<td align="left">Evaluation when required</td>
<td align="left">1h</td>
</tr>
<tr class="odd">
<td align="left"><a href="#typeclasses">Type-Classes</a></td>
<td align="left">Polymorphism, FP style</td>
<td align="left">30m</td>
</tr>
<tr class="even">
<td align="left"><a href="#music">Wildcard</a></td>
<td align="left">Music</td>
<td align="left">30m</td>
</tr>
<tr class="odd">
<td align="left"><a href="#monads">Monads</a></td>
<td align="left">IO Monad, Do-Notation</td>
<td align="left">1h</td>
</tr>
<tr class="even">
<td align="left"><a href="#ecosystem">Ecosystem</a></td>
<td align="left">Resources and Community</td>
<td align="left">30m</td>
</tr>
<tr class="odd">
<td align="left"><a href="#moar">~ MOAR!! ~</a></td>
<td align="left">Awesome Extras!</td>
<td align="left">~</td>
</tr>
<tr class="even">
<td align="left"><a href="#testing">Testing</a></td>
<td align="left">Testing with QuickCheck</td>
<td align="left">1h</td>
</tr>
<tr class="odd">
<td align="left"><a href="#symbolic-differentiation">Algebra</a></td>
<td align="left">Symbolic Mathematics</td>
<td align="left">30m</td>
</tr>
<tr class="even">
<td align="left"><a href="#website">Web-Site</a></td>
<td align="left">Making a Web-Site with Scotty</td>
<td align="left">30m</td>
</tr>
<tr class="odd">
<td align="left"><a href="#compression">Compression</a></td>
<td align="left">Compression</td>
<td align="left">1h</td>
</tr>
<tr class="even">
<td align="left"><a href="#appendix">Appendix</a></td>
<td align="left">Appendix</td>
<td align="left">~</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
<div class='chapter'>
<div class='content'>
<hr />
<h1 id="required-resources">Required Resources</h1>
<p>Before you begin you will require the following...</p>
<h2 id="a-text-editor" class="important">A Text-Editor</h2>
<p>We are assuming previous programming experience, however, if you would like a recommendation, have a look at <a href="https://atom.io/">Atom</a>, <a href="http://notepad-plus-plus.org/">Notepad++</a>, <a href="http://www.sublimetext.com/">Sublime Text</a>, or the ever-popular <a href="http://www.gnu.org/software/emacs/">Emacs</a> and <a href="http://www.vim.org/">Vim</a>. Just make sure that you are fluent enough to embark on exercises as they appear in the workshop.</p>
<h2 id="the-haskell-platform" class="important"><a href="http://www.haskell.org/platform/">The Haskell Platform</a></h2>
<p>In order to run the programs written during this workshop you will need a Haskell installation. The easiest way to get up and running is to install the latest Haskell Platform. This is a "batteries included" installation of GHC and Cabal that includes many of the most useful packages available in the Hackage ecosystem.</p>
<h2 id="a-copy-of-the-workshop-scaffold-project" class="important"><a href="https://github.com/sordina/haskell_workshop_2015">A Copy of the Workshop Scaffold Project</a></h2>
<p><a href="https://github.com/sordina/haskell_workshop_2015" class="uri">https://github.com/sordina/haskell_workshop_2015</a></p>
<p>Either clone with git:</p>
<pre class="shell"><code>git clone https://github.com/sordina/haskell_workshop_2015.git</code></pre>
<p>... or <a href="https://github.com/sordina/haskell_workshop_2015/archive/master.zip">download the zip</a> from GitHub.</p>
<h1 id="useful-resources" class="collapse">Useful Resources</h1>
<p>These resources are available to help you with any issues you face when learning Haskell:</p>
<h2 id="haskell-on-freenode">#haskell on <a href="http://freenode.net/">Freenode</a></h2>
<p>An IRC channel dedicated to discussion of Haskell. This is often the easiest place to fire off a one-off question that is simple enough not to warrant a permanent listing on the internet.</p>
<h2 id="hackage"><a href="http://hackage.haskell.org/packages/hackage.html">Hackage</a></h2>
<p>Hackage is the primary repository for Haskell packages. It is public, searchable, versioned, and uses Cabal package metadata for classification. Furthermore, this can be used to easily browse package contents, documentation and source-code.</p>
<p>For example, browse the <a href="http://hackage.haskell.org/package/shake">Shake</a> package and look at some of the <a href="http://hackage.haskell.org/packages/archive/shake/0.10.6/doc/html/Development-Shake-Command.html">Modules</a>.</p>
<h2 id="hoogle"><a href="http://www.haskell.org/hoogle/">Hoogle</a></h2>
<p>Hoogle is a Haskell module and function search-engine. Hoogle allows you to take advantage of the granular type-system used by Haskell to search not just for function-names, but for function type-signatures.</p>
<p>For example, have a look for the function with signature <a href="http://www.haskell.org/hoogle/?hoogle=Text+-%3E+ByteString">Text -> ByteString</a>.</p>
<h2 id="mfug"><a href="http://www.meetup.com/Melbourne-Functional-User-Group-MFUG/">MFUG</a></h2>
<p>MFUG is the Melbourne Functional Programmer's User Group. This group discusses many topics, including Haskell.</p>
<h2 id="rhaskell"><a href="http://www.reddit.com/r/haskell">/r/haskell</a></h2>
<p>For Reddit users, /r/haskell is a very useful resource with a great deal of information regarding recent developments in the Haskell ecosystem and community. This is a good place to ask some more advanced questions or start a flame-war.</p>
<h2 id="haskell-news"><a href="http://haskellnews.org/">Haskell News</a></h2>
<p>Haskell News is a firehose-style haskell news aggregator taking information from sources as varied as academic-journals, and GitHub accounts.</p>
<h2 id="hlint"><a href="http://hackage.haskell.org/package/hlint">HLint</a></h2>
<p>HLint is a <a href="http://en.wikipedia.org/wiki/Lint_(software)">linting tool</a> for Haskell source - It can often provide some useful hints about refactoring avenues for your code.</p>
<h2 id="learn-you-a-haskell-for-great-good"><a href="http://learnyouahaskell.com/">Learn You a Haskell (For Great Good)</a></h2>
<p>Learn You a Haskell (For Great Good) is a wonderful introductory text on Haskell.</p>
<h2 id="real-world-haskell"><a href="http://book.realworldhaskell.org/">Real World Haskell</a></h2>
<p>Real World Haskell aims to focus on solving real problems with Haskell. Several chapters of the book are somewhat dated in terms of the libraries used, but it still serves as a useful example of getting real work done with Haskell.</p>
</div>
</div>
<div class='chapter'>
<div class='content'>
<hr />
<h1 id="welcome">Welcome</h1>
<div class="important">
<p>Welcome to the Melbourne Haskell Workshop 2015.</p>
<p>This intent of this workshop is to provide a working introduction to Haskell for programmers in Melbourne who have not yet used the language in anger.</p>
<p>The workshop is split into chapters. The chapters will start with a few trivial introductory exercises to get your fingers warmed up, then the meat - exercises that should be able to be solved using the material introduced up to that point (with help and hints available if needed).</p>
<p>Each chapter will conclude with an open-question. This question should provide inspiration for further consideration of how harder problems could be solved using Haskell, and for more advanced attendees, can be attacked instead of twiddling your thumbs after finishing the main exercise.</p>
<p>The workshop will be split into pre, and post lunch parts, with additional exercises available for busy beavers following the <a href="#moar">MOAR</a> section of the table of contents.</p>
</div>
<h2 id="why-run-a-free-haskell-workshop">Why run a free haskell workshop?</h2>
<p>There are a few kinds of benefits that we anticipate will result as an outcome of the workshop:</p>
<ul>
<li>Benefits to Individuals</li>
<li>Benefits to the Community</li>
<li>Benefits to the Volunteers</li>
<li>Benefits to the Organisers</li>
<li>Benefits to Industry</li>
<li>Benefits to Relationships</li>
</ul>
<h3 id="benefits-to-individuals">Benefits to Individuals</h3>
<ul>
<li>New Tools</li>
<li>Experience writing Haskell</li>
<li>An Introduction to the Wider Community</li>
</ul>
<p>What do we hope that an individual attendee will gain by coming to the workshop?</p>
<p>Since this workshop is targeted towards beginners, we want an attendee to come away from the workshop with new tools at their disposal. Yes, a new language to reimplement existing knowledge with various platform benefits, but more importantly, a new tool for dissecting problems.</p>
<p>Learning a new problem-solving approach will almost certainly be the most challenging part of the workshop, but through the consistent delivery of exercises that benefit from domain modelling, we hope that the attendee will walk away with the confidence to attack new problems from the "Haskell Mindset".</p>
<p>Although there won't be time to work on any large-scale problems, we hope that the approaches we demonstrate will be able to be applied with confidence to problems of any size.</p>
<p>Aside from the technical benefits, the workshop should provide a great opportunity for attendees to meet many other members of the Melbourne Haskell using community.</p>
<h3 id="benefits-to-the-community">Benefits to the Community</h3>
<ul>
<li>Haskell as a Tool for Communication</li>
<li>Local Network Effects</li>
<li>Consolidation</li>
</ul>
<p>Often, Haskell (especially the type-system) can be an extremely effective means of communication of certain kinds of behaviors, requirements, and problems. If this workshop can help advance Haskell as a common language for inter-personal discussion of technical topics, then the barriers of communication will be lowered and the community as a whole should become more productive.</p>
<p>Often, it isn't until a particular community reaches a critical mass that it comes into its own. Currently the Melbourne Haskell community is reasonably disparate and unconnected (especially outside of MFUG). If the various groups of people using Haskell can be consolidated, then we would consider starting a regular Melbourne Haskell meetup. Just having the ability to ask questions in person can go a long way to advancing confidence in a particular topic, therefore, as the number of Haskell users increases locally, so to will the overall skill of individuals and the community as a whole.</p>
<h3 id="benefits-to-the-volunteers">Benefits to the Volunteers</h3>
<ul>
<li>Experience</li>
<li>Networking</li>
</ul>
<p>We hope that for the volunteers, providing administrative and in-person assistance will be a rewarding experience. We are very open to people of any skill level helping out and this could be a great opportunity for newcomers to the community to get their fingers dirty by providing assistance at the workshop.</p>
<p>The workshop should also be a good networking opportunity for volunteers, as a stratified group of Haskellers of this size has not yet convened in Melbourne.</p>
<h3 id="benefits-to-industry">Benefits to Industry</h3>
<p>It has been said that once you are comfortable programming Haskell, you become spoiled, and won't want to go back to your previous languages. Rather than quit your day-job, if Haskell's presence can be advanced in industry, then the Joy of programming haskell will become a possibility in your day-to-day work-life. A longer-term goal to be sure.</p>
<p>This benefit may be the most tenuous outcome of the workshop, but as the mindshare of Haskell grows, the chances of it being used for projects within industry increases.</p>
<ul>
<li>As an understanding of the language's strengths and weaknesses emerges, decision makers are empowered to weigh up if the language is a suitable candidate for solving the technical problems at hand.</li>
<li>Confidence is gained that there are enough people using the language that hiring a programmer will not be a problem if this is required.</li>
</ul>
<p>The technical benefits to industry will have the most impact where a rigorous solution to a problem is necessary. In the financial sector, Haskell is beginning to become more popular as the cost of bugs can be very high. Technical benefits, however, are a moot point if Haskell does not see adoption.</p>
<p>If this workshop can give project-leaders in industry, making programming-language choices, the confidence to consider Haskell as a real candidate, then it will have gone a long way towards making Melbourne a more attractive place to be for people who wish to use Haskell in day-to-day work.</p>
<h3 id="benefits-to-the-organisers">Benefits to the Organisers</h3>
<p>Last-but-not-least -</p>
<div class="important">
<p>For us, the organisers, running this workshop will be a great opportunity to see the Melbourne Haskell community in action. We're looking forward to working with you all and expect that, above all else, we will have a lot of...</p>
<h2 id="fun"><em>Fun!</em></h2>
</div>
</div>
</div>
<div class='chapter'>
<div class='content'>
<hr />
<h1 id="setup">Setup</h1>
<div class="important">
<p>Ensure that you have the following programs installed and functioning correctly:</p>
<h2 id="ghci">GHCi</h2>
</div>
<p>At a command prompt, enter the following command:</p>
<pre class="shell"><code>ghci</code></pre>
<p>This should launch the GHC Haskell REPL.</p>
<p>Type the following to ensure that you have a functioning REPL:</p>
<pre data-language="haskell"><code>1 + 1</code></pre>
<p>This should yield the result:</p>
<pre class="text"><code>2</code></pre>
<pre class="real"><code>You can use GHCi to perform calculations other than just "1 + 1".
Here is an example session:
> ghci
GHCi, version 7.6.2: http://www.haskell.org/ghc/ :? for help
Loading package ghc-prim ... linking ... done.
Loading package integer-gmp ... linking ... done.
Loading package base ... linking ... done.
[Prelude] > 1 + 2 + 3
6
[Prelude] > 100 / 2
50.0
[Prelude] > 6 ^ 7
279936
[Prelude] > ^D
Leaving GHCi.</code></pre>
<pre class="instruction"><code>Using GHCi...
Calculate the price of 42-bakers-dozens of eggs at $3 per-egg.</code></pre>
<pre class="answer"><code>[Prelude] 42 * 13 * 3
1638</code></pre>
<h2 id="loading-files-in-ghci" class="important">Loading files in GHCi</h2>
<p>There are many ways to load and execute Haskell code. For the purposes of this workshop, if you do not already have a workflow you are comfortable with, then we suggest the following steps:</p>
<ul>
<li>Write and edit your programs in files ending in the extension ".hs"</li>
<li>When you are ready to test your program, load it into GHCi</li>
<li>After making modifications to your program, reload the program in GHCi</li>
</ul>
<p>Say you had written the following program <code>test.hs</code> in your home directory:</p>
<pre data-language="haskell" data-filter="./resources/scripts/check.sh"><code>main = print "hello world"
</code></pre>
<p>Load the file in GHCi to see it in action:</p>
<pre class="shell"><code>> ghci test.hs
GHCi, version 7.6.2: http://www.haskell.org/ghc/ :? for help
Loading package ghc-prim ... linking ... done.
Loading package integer-gmp ... linking ... done.
Loading package base ... linking ... done.
[1 of 1] Compiling Main ( test.hs, interpreted )
Ok, modules loaded: Main.
[*Main] > main
"hello world"</code></pre>
<p>... Unfortunately there is a bug in the program, so in your editor you make the change required to print "hello, world" with the mandated comma:</p>
<pre data-language="haskell" data-filter="./resources/scripts/check.sh"><code>main = print "hello, world"
</code></pre>
<p>Now, back in GHCi, you can reload the program without exiting the REPL:</p>
<pre class="shell"><code>[*Main] > :reload
[1 of 1] Compiling Main ( test.hs, interpreted )
Ok, modules loaded: Main.
[*Main] > main
"hello, world"</code></pre>
<p>Much better!</p>
<pre class="real"><code>You can inspect a value (of function) in ghci with the `:info` command
in order to find out a little about its type and definition:
ghci> :info main
main :: IO () -- Defined at test.hs:1:1
If you just wish to see the type of an expresison, you can use
the `:type` command:
ghci> :type main
main :: IO ()</code></pre>
<pre class="instruction"><code>
* Define a new numeric function in a source file
* Load it in GHCi
* Test your function in GHCi
* Make a modification
* Reload your chages without exiting GHCi
* Test your changes</code></pre>
<h2 id="ghc" class="important">GHC</h2>
<p>Create the following source file (program.hs):</p>
<pre data-language="haskell"><code>main = print "hello world"</code></pre>
<p>Compile the program as follows:</p>
<pre class="shell"><code>ghc --make program.hs</code></pre>
<p>Run the program with the following command:</p>
<pre class="shell"><code>./program</code></pre>
<p>The output should look as follows:</p>
<pre class="text"><code>"hello world"</code></pre>
<pre class="real"><code>Compiled programs are almost always significantly faster than instructions
run inside GHCi. Even greater speed-ups are possible by using the "-O"
optimisation settings for GHC.</code></pre>
<pre class="instruction"><code>Using GHC...
Compile and run hello-world.</code></pre>
<pre class="answer"><code>> echo 'main = print "hello friends"' > main.hs
> ghc --make main.hs
[1 of 1] Compiling Main ( main.hs, main.o )
Linking main ...
> ./main
"hello friends"</code></pre>
<h2 id="cabal" class="important">Cabal</h2>
<p>You should have access to a Cabal installation if you have installed the Haskell Platform.</p>
<p>Check that you have cabal by running:</p>
<pre class="shell"><code>cabal --version</code></pre>
<p>This should output something similar to:</p>
<pre class="text"><code>cabal-install version <VERSION>
using version <VERSION> of the Cabal library</code></pre>
<pre class="instruction"><code>Install the QuickCheck package using cabal.</code></pre>
<pre class="note"><code>On OS X, The Haskell-Platform will install binaries in
$HOME/Library/Haskell/bin
Make sure that this is on your path.</code></pre>
<pre class="answer"><code>> cabal update # not required if done recently
Downloading the latest package list from hackage.haskell.org
> cabal install quickcheck
...</code></pre>
<pre class="open"><code>An open-ended question:
Given that GHC is largely written in Haskell, how was GHC first compiled?</code></pre>
<pre class="open"><code>An open-ended question:
What are some of the current issues with the Haskell ecosystem?</code></pre>
</div>
</div>
<div class='chapter'>
<div class='content'>
<hr />
<h1 id="introduction">Introduction</h1>
<div class="important">
<p>The following exercises are intended to be used to warm up your fingers, rather than your brain. These should be run through quickly to get you used to using your development environment.</p>
</div>
<h2 id="primitives">Primitives</h2>
<p>Haskell comes pre-packaged with many primitives available in the <code>Prelude</code> module that is included by default, but you should at least make yourself familiar with the following types, and literal syntax:</p>
<table style="width:54%;">
<colgroup>
<col width="16%" />
<col width="18%" />
<col width="18%" />
</colgroup>
<thead>
<tr class="header">
<th align="left">What?</th>
<th align="left">Type</th>
<th align="left">Literal Syntax</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td align="left">Machine Ints</td>
<td align="left">Int</td>
<td align="left">42</td>
</tr>
<tr class="even">
<td align="left">Strings</td>
<td align="left">String, [Char]</td>
<td align="left">"Hello World"</td>
</tr>
<tr class="odd">
<td align="left">Booleans</td>
<td align="left">Bool</td>
<td align="left">True , False</td>
</tr>
</tbody>
</table>
<pre class="real"><code>You can type any literal directly into GHCi in order to have it echoed right
back at you. This may be useful for sanity checking that you have the syntax
right!
ghci> 42
42</code></pre>
<h2 id="variables">Variables</h2>
<p>In Haskell you can define a variable with the <code>=</code> sign.</p>
<p>Variables can be defined at the top-level (no-indentation):</p>
<pre data-language="haskell" data-filter="./resources/scripts/check.sh"><code>myVariable = 2
</code></pre>
<p>Variable names should start with a lowercase letter and contain no spaces, or special characters, besides underscores, numbers, and <code>'</code>.</p>
<pre class="real"><code>If you wish to define a variable inside GHCi, you have to prefix
the definition with "let"... For example:
[Prelude] > let myName = "Simon"</code></pre>
<p>Some examples of variable names are:</p>
<ul>
<li><code>a</code></li>
<li><code>my_name</code></li>
<li><code>data43'</code></li>
</ul>
<pre class="instruction"><code>Define your own variable.</code></pre>
<pre class="answer" data-language="haskell" data-filter="./resources/scripts/check.sh"><code>x = "hello"
</code></pre>
<pre class="instruction"><code>What is an example of an invalid variable name?</code></pre>
<pre class="answer nocheck" data-language="haskell"><code>invalid-variable = 123</code></pre>
<p>String literals look familiar:</p>
<pre data-language="haskell" data-filter="./resources/scripts/check.sh"><code>myString = "hello world"
</code></pre>
<pre class="instruction"><code>Define a variable containing a string.</code></pre>
<h2 id="tuples">Tuples</h2>
<p>Tuples look like this:</p>
<pre data-language="haskell" data-filter="./resources/scripts/check.sh"><code>myTuplePair = (1,"hello")
myTupleTrio = (1,"hello",3)
</code></pre>
<p>They can be used to group multiple, differently-typed (heterogeneous) values.</p>
<pre class="instruction"><code>Define a variable containing a tuple.</code></pre>
<h2 id="functions">Functions</h2>
<p>Functions are a core part of Haskell. Function definitions look like this:</p>
<pre class="nocheck" data-language="haskell"><code>myFunction x y ... = ...</code></pre>
<p>For example:</p>
<pre data-language="haskell" data-filter="./resources/scripts/check.sh"><code>myAdd x y = x + y
</code></pre>
<p><code>myAdd</code> takes two numbers and returns the result of the addition of those two numbers.</p>
<pre class="instruction"><code>Define a function `myMultiply` that multiplies 3 numbers.</code></pre>
<pre class="answer" data-language="haskell" data-filter="./resources/scripts/check.sh"><code>myMultiply x y z = x * y * z
</code></pre>
<h2 id="lists">Lists</h2>
<p>List are a commonly used data-structure in Haskell. Everything in a list has the same type (they are homogeneous).</p>
<p>Lists are built using the infix data-constructor <code>(:)</code> (pronounced "cons"). They also have a compact notation using <code>[...]</code>.</p>
<p>List literals look like:</p>
<pre data-language="haskell" data-filter="./resources/scripts/check.sh"><code>list1 = [1,2,3]
list2 = 1 : 2 : []
list3 = "hello" : "world" : []
</code></pre>
<p>More information about why lists can be used the way that they are is contained in the <a href="#adts-algebraic-data-types">ADTs</a> chapter.</p>
<pre class="instruction"><code>Define a variable containing a list.</code></pre>
<p>You can deconstruct a list by pattern matching the head and tail like so:</p>
<pre class="nocheck" data-language="haskell"><code>f (x:xs) = ...</code></pre>
<pre class="instruction"><code>Define a function to get the first element of a list.</code></pre>
<pre class="answer" data-language="haskell" data-filter="./resources/scripts/check.sh"><code>myHead (x:xs) = x -- This is a partial function, Beware!
</code></pre>
<p>In <code>Prelude</code> this function is called <code>head</code>.</p>
<pre class="note"><code>"head" is a partial function - It will raise an exception if
called with an empty list.
In Haskell we generally wish to avoid defining partial functions.</code></pre>
<pre class="instruction"><code>Define a variable containing the first element of your list.</code></pre>
<pre class="answer nocheck" data-language="haskell"><code>myFirstElement = myHead myList</code></pre>
<h3 id="define-length">Define Length</h3>
<pre class="instruction"><code>Define a function that takes a list and returns the length.</code></pre>
<p>Your solution should have the form of:</p>
<pre class="nocheck" data-language="haskell"><code>myLength [] = ...
myLength (x:xs) = ...</code></pre>
<p>Things to consider:</p>
<ul>
<li>What is the length of an empty list? (the base case)</li>
<li>What is the length of xs?</li>
</ul>
<pre class="answer" data-language="haskell" data-filter="./resources/scripts/check.sh"><code>myLength [] = 0
myLength (x:xs) = 1 + myLength xs
</code></pre>
<h3 id="define-mymap">Define <code>myMap</code></h3>
<pre class="instruction"><code>
Define a function that takes a function from a to b,
and a list of 'a', and returns a list of 'b's.</code></pre>
<p>Some concrete examples of such a function may do the following:</p>
<ul>
<li>Take a function that divides integers by two, list of ints, and returns a list of doubles.</li>
<li>Take a function that turns lowercase into uppercase characters, and a String, and returns a string in CAPS.</li>
</ul>
<p>Things to consider:</p>
<ul>
<li>What is the base-case of myMap?</li>
<li>What is the inductive-case of myMap?</li>
</ul>
<pre class="answer" data-language="haskell" data-filter="./resources/scripts/check.sh"><code>myMap f [] = []
myMap f (x:xs) = f x : myMap f xs
</code></pre>
<h2 id="fun-list-functions">Fun List Functions</h2>
<p>For your reading pleasure, here are some definintions of common functions:</p>
<pre data-language="haskell" data-filter="./resources/scripts/check.sh"><code>myFilter f [] = []
myFilter f (x:xs) = if f x then x : myFilter f xs
else myFilter f xs
myFold f z [] = z
myFold f z (x:xs) = f x (myFold f z xs)
myReverse [] = []
myReverse (x:xs) = myReverse xs ++ [x]
myElem e [] = False
myElem e (x:xs) = if e == x then True
else myElem e xs
</code></pre>
<pre class="open"><code>An open-ended question:
What is a good balance between safety and expressiveness in a
programming-language?</code></pre>
</div>
</div>
<div class='chapter'>
<div class='content'>
<hr />
<h1 id="types">Types</h1>
<pre class="note.notitle"><code>Question: How do you create a great program?
Answer: You type it!</code></pre>
<p>In this chapter, we will go over the exercises from the introduction and add types to the examples.</p>
<hr />
<p>In Haskell, type signatures can be provided inline, or above definitions.</p>
<p>For example:</p>
<pre data-language="haskell" data-filter="./resources/scripts/check.sh"><code>x :: Int
x = 3
</code></pre>
<p>or</p>
<pre data-language="haskell" data-filter="./resources/scripts/check.sh"><code>x = (3 :: Int)
</code></pre>
<p>It is far more common to place the type-signature above the definition, with inline types only used in situations where ambiguities need to be resolved.</p>
<div class="important">
<pre class="instruction nobefore"><code>You are defining a floating point variable:</code></pre>
<pre data-language="haskell" data-filter="./resources/scripts/check.sh"><code>myFloat = 1.1
</code></pre>
<pre class="instruction"><code>Give your variable a type-signature.</code></pre>
<pre class="answer" data-language="haskell" data-filter="./resources/scripts/check.sh"><code>myFloat :: Float
myFloat = 1.1
</code></pre>
</div>
<h2 id="type-synonyms">Type Synonyms</h2>
<p>In Haskell, we can give type-expressions an alias (or synonym) by using the <code>type</code> keyword. This allows you to cut down the verbosity and chance of errors in your code when you have type expressions that would otherwise be repeated frequently.</p>
<p>An example of this is the <code>String</code> type-synonym, which is defined as follows:</p>
<pre class="nocheck" data-language="haskell"><code>type String = [Char]</code></pre>
<pre class="instruction"><code>
Give your string variable from the previous chapter a type-signature.</code></pre>
<pre class="answer" data-language="haskell" data-filter="./resources/scripts/check.sh"><code>myString :: String
myString = "Hello Haskell"
</code></pre>
<h2 id="tuples">Tuples</h2>
<p>Tuple type signatures look the same as the tuples themselves, with types in place of the data.</p>
<p>For example, if you had a tuple of a String and an Int, the type would look as follows:</p>
<pre data-language="haskell" data-filter="./resources/scripts/check.sh"><code>myTuple :: (String, Int)
myTuple = ("The meaning of life", 42)
</code></pre>
<pre class="instruction"><code>Give your previous tuple definition a type signature.</code></pre>
<h2 id="functions">Functions</h2>
<p>The type signatures of functions in Haskell are a little different from how they look in the more familiar C family languages, but the syntax is very elegant, and will allow a higher-level of reasoning than less consistant forms.</p>
<p>The syntax for a function type-signarure is of the form:</p>
<pre class="nocheck" data-language="haskell"><code>{functionName} :: {argument} -> {result}</code></pre>
<p>The main idea is that functions in Haskell only ever take one argument. If you wish to define a function that takes more than one argument, then you should, infact, define a function that takes one argument, then returns another function.</p>
<p>Luckily the syntax for doing this in Haskell looks identical to defining a multi-argument function:</p>
<pre data-language="haskell" data-filter="./resources/scripts/check.sh"><code>myMultiply x y z = x * y * z
</code></pre>
<p>However, the distinction becomes clear with the type-signature:</p>
<pre data-language="haskell" data-filter="./resources/scripts/check.sh"><code>myMultiply :: Int -> (Int -> (Int -> Int))
myMultiply x y z = x * y * z
</code></pre>
<p>It is clear, that the function only takes one argument, then returns a function (that only takes one argument, and returns a function (that only takes one argument, that returns an Int.))</p>
<p>Fortunately, Haskell's function syntax is right-associative, allowing us to drop the parentheses:</p>
<pre data-language="haskell" data-filter="./resources/scripts/check.sh"><code>myMultiply :: Int -> Int -> Int -> Int
myMultiply x y z = x * y * z
</code></pre>
<pre class="instruction"><code>
Define a function `myMultiply` that multiplies 4 numbers.
Give your function a type-signature</code></pre>
<pre class="answer" data-language="haskell" data-filter="./resources/scripts/check.sh"><code>myMultiply :: Int -> Int -> Int -> Int -> Int
myMultiply w x y z = w * x * y * z
</code></pre>
<h2 id="lists">Lists</h2>
<p>List type-signatures look like:</p>
<pre data-language="haskell" data-filter="./resources/scripts/check.sh"><code>list1 :: [Int]
list2 :: [Int]
list3 :: [String]
list1 = [1,2,3]
list2 = 1 : 2 : []
list3 = "hello" : "world" : []
list1A :: ([]) Int
list1A = [1]
</code></pre>
<p>List type signatures are special in that the type-constructor is "Around"-fix. This is not generally possible, and lists are a special case in that regard.</p>
<p>If you find you need to, you can use the list type in prefix-form, as per variable <code>list1A</code>.</p>
<pre class="instruction"><code>Define a list variable and give it a type-signature.</code></pre>
<pre class="answer" data-language="haskell" data-filter="./resources/scripts/check.sh"><code>myList :: [Int]
myList = [1,2,3]
</code></pre>
<pre class="instruction"><code>Give your `head` deconstructor function a type-signature.</code></pre>
<pre class="answer" data-language="haskell" data-filter="./resources/scripts/check.sh"><code>myHead :: [a] -> a
myHead (x:xs) = x
</code></pre>
<h3 id="length-signature">Length Signature</h3>
<pre class="instruction"><code>Give your length function a type-signature.</code></pre>
<pre class="answer" data-language="haskell" data-filter="./resources/scripts/check.sh"><code>myLength :: [a] -> Int
myLength [] = 0
myLength (x:xs) = 1 + myLength xs
</code></pre>
<h3 id="map-signature">Map Signature</h3>
<pre class="instruction"><code>Give your `map` function a type-signature.</code></pre>
<p>Things to consider:</p>
<ul>
<li>What is the type of the first argument of myMap?</li>
<li>What is the second argument, etc?</li>
<li>What is the type of the result of myMap?</li>
</ul>
<pre class="answer" data-language="haskell" data-filter="./resources/scripts/check.sh"><code>myMap :: (a -> b) -> [a] -> [b]
myMap f [] = []
myMap f (x:xs) = f x : myMap f xs
</code></pre>
<h2 id="fun-list-functions-types">Fun List Functions Types</h2>
<p>Here are the types for the definintions of the list functions from the previous chapter:</p>
<pre data-language="haskell" data-filter="./resources/scripts/check.sh"><code>myFilter :: (a -> Bool) -> [a] -> [a]
myFilter f [] = []
myFilter f (x:xs) = if f x then x : myFilter f xs
else myFilter f xs
myFold :: (a -> b -> b) -> b -> [a] -> b
myFold f z [] = z
myFold f z (x:xs) = f x (myFold f z xs)
myReverse :: [a] -> [a]
myReverse [] = []
myReverse (x:xs) = myReverse xs ++ [x]
myElem :: Eq a => a -> [a] -> Bool
myElem e [] = False
myElem e (x:xs) = if e == x then True
else myElem e xs
</code></pre>
<pre class="instruction"><code>Try to understand the type-signatures for these functions.
Hint: Try finding a way to say them in English.</code></pre>
<pre class="open"><code>An open-ended question:
How many types could a type-checker check...
... if a type checker could check types?</code></pre>
</div>
</div>
<div class='chapter'>
<div class='content'>
<hr />
<h1 id="adts-algebraic-data-types">ADTs (Algebraic Data Types)</h1>
<div class="center">
<p><a href="http://www.haskell.org/haskellwiki/Algebraic_data_type">Haskell Wiki Link</a></p>
</div>
<p>Algebraic Data Types are THE bread and butter of Haskell programs.</p>
<ul>
<li>Functions evaluate data by pattern-matching against ADTs</li>
<li>Domains are modeled using ADTs</li>
<li>Laziness is linked to ADTs</li>
<li>Types can be derived from ADT definitions</li>
</ul>
<div class="collapse">
<p>But how does that help me?</p>
<p>An example of an ADT in Haskell:</p>
<pre data-language="haskell" data-filter="./resources/scripts/check.sh"><code>data MyBool = MyTrue | MyFalse | MyNotSure
should_I_eat_something_bigger_than_my_own_head :: MyBool
should_I_eat_something_bigger_than_my_own_head = MyFalse
</code></pre>
<pre class="real"><code>With this functionality, you are able to introduce your own "Enum"
values.
The MyBool example is somewhat equivalent to the following C++ code:
enum MyBool { MyTrue, MyFalse, MyNotSure };
With the added bonus of not having out-of-bounds casting ruin your day.
If your problem space can be moddeled using various discrete values,
then this form of ADT will allow you to create a program that mirrors
your problem!</code></pre>
<p>You can add parameters to the data constructors:</p>
<pre data-language="haskell" data-filter="./resources/scripts/check.sh"><code>data MyNullString = Nada | MyString String
stringy :: MyNullString
stringy = MyString "Whatever, It's just a string"
blanky :: MyNullString
blanky = Nada
</code></pre>
<p>Constructors can take multiple parameters:</p>
<pre data-language="haskell" data-filter="./resources/scripts/check.sh"><code>data SomeJunk = Rubbish String | TrashPile String Int Bool
discards :: SomeJunk
discards = TrashPile "Junk Yard" 42 True
</code></pre>
<p>Furthermore, ADTs can be recursive:</p>
<pre data-language="haskell" data-filter="./resources/scripts/check.sh"><code>data MyNumberList = Nada | SomeNumbers Int MyNumberList
numbers :: MyNumberList
numbers = SomeNumbers 1 (SomeNumbers 2 Nada)
</code></pre>
<p>Finally, ADTs can be parametrised by other types:</p>
<pre data-language="haskell" data-filter="./resources/scripts/check.sh"><code>data MyContainer x = Jar x
contained :: MyContainer Int
contained = Jar 1
pun :: MyContainer (MyContainer String)
pun = Jar (Jar "Binks")
</code></pre>
<p>In general, the syntax of an ADT looks similar to the following:</p>
<pre class="bnf"><code>ADT := data <TypeName> <Variables> = <Constructors>
TypeName := [A-Z] + [a-z'_]*
Parameters := <ConcreteType> + (" " + <ConcreteType>)*
Constructors := <Constructor> + (" | " + <Constructor>)*
Constructor := <TypeName> + <Parameters>
Variables := <Variable> + (" " + <Variable>)*
Variable := [a-z] + [a-z'_]*</code></pre>
<p>ConcreteType can't be defined syntactically, but it means that your type is "Fully Applied" (in Haskell terms, has a kind of <code>*</code>). An example of some concrete types are:</p>
<ul>
<li><code>String</code></li>
<li><code>Int</code></li>
<li><code>Maybe String</code></li>
<li><code>[Int]</code></li>
</ul>
<p>Examples of some non-concrete types are:</p>
<ul>
<li><code>Maybe</code></li>
<li><code>IO</code></li>
<li><code>(->)</code></li>
</ul>
<h2 id="deriving">Deriving</h2>
<p>One final thing to note is that in order to be able to print values of your data types at the GHCi REPL, you will need your data to be a member of the <code>Show</code> type-class.</p>
<p><em>Type-classes are covered in depth in the <a href="#typeclasses">type-classes</a> chapter.</em></p>
<p>This is achieved by appending the following text after your data definition:</p>
<pre data-language="haskell" data-filter="./resources/scripts/check.sh"><code>data MyData = SuperGreat deriving (Show)
</code></pre>
<p>Similar classes are needed for ordering and equality. If you get stuck on a missing class, just add the following deriving triple for now:</p>
<pre data-language="haskell" data-filter="./resources/scripts/check.sh"><code>data MyData = SuperGreat deriving (Eq, Ord, Show)
</code></pre>
<h2 id="exercises">Exercises</h2>
<p>With all of this power at your disposal, it's time to define a list ADT yourself.</p>
</div>
<pre class="instruction"><code>Define your own generic list ADT.</code></pre>
<p>Things to consider:</p>
<ul>
<li>Should this ADT be parametrised?</li>
<li>Should this ADT be recursive?</li>
<li>Should this ADT have multiple constructors?</li>
<li>Should the constructors be parametrised?</li>
</ul>
<pre class="answer" data-language="haskell" data-filter="./resources/scripts/check.sh"><code>data MyList a = Empty | Items a (MyList a)
</code></pre>
<pre class="open"><code>An open-ended question:
What would the ADT for a Lisp-like language look like?</code></pre>
<div class="note">
<p>If you wish to learn about why ADTs are "Algebraic", then have a look at:</p>
<ul>
<li><a href="http://chris-taylor.github.io/blog/2013/02/10/the-algebra-of-algebraic-data-types/">The Algebra of Algebraic Data Types, Part 1</a></li>
<li><a href="http://chris-taylor.github.io/blog/2013/02/11/the-algebra-of-algebraic-data-types-part-ii/">The Algebra of Algebraic Data Types, Part 2</a></li>
<li><a href="http://chris-taylor.github.io/blog/2013/02/13/the-algebra-of-algebraic-data-types-part-iii/">The Algebra of Algebraic Data Types, Part 3</a></li>
</ul>
</div>
</div>
</div>
<div class='chapter'>
<div class='content'>
<hr />
<h1 id="lunch-break">Lunch Break</h1>
<div class="center important">
<p>Lunch is provided courtesy of <a href="http://www.thoughtworks.com/">ThoughtWorks</a></p>
<div class="center">
<img src="resources/images/chicken.png" alt="Chicken Dinner" />
</div>
</div>
</div>
</div>
<div class='chapter'>
<div class='content'>
<hr />
<h1 id="laziness">Laziness</h1>
<div class="center">
<p><em>Haskell's evaluation strategies ~ Exploring the magic.</em></p>
</div>
<p>Often when looking at examples of Haskell functions you will come across examples of laziness in action. The canonical example used to demonstrate the lazy recursive approach of Haskell is the definition of the list of Fibonacci numbers -</p>
<pre data-language="haskell" data-filter="./resources/scripts/check.sh"><code>fibs = 1 : 1 : zipWith (+) fibs (tail fibs)
</code></pre>
<p>This solution has a reputation for being somewhat mind-bending for beginners... What is going on here?</p>
<pre class="real"><code>In order to show the start of an infinite list, use the `take` function -
For example:
[Prelude] > let fibs = 1 : 1 : zipWith (+) fibs (tail fibs)
[Prelude] > take 10 fibs
[1,1,2,3,5,8,13,21,34,55]</code></pre>
<p>Here is a Fibonacci solution in Javascript:</p>
<pre data-language="javascript"><code>function fib(n) {
if(n < 2) return 1
return fib(n-1) + fib(n-2)
}</code></pre>
<p>Most programmers won't have any problem with the usual recursive definition of <code>fibs</code>, so what makes the Haskell one special? Let's see if we can implement the Haskell version in Javascript:</p>
<pre data-language="javascript"><code>// The Fibonacci Sequence in all its glory~
//
function fibs() { return [1, cons(1, zipWith(add, fibs, tail( fibs )))] }
exports.main = function() { runList(fibs, 13) }
// Helpers
//
function cons(h,t) { return function() { return [h,t] }}
function head(list) { return list()[0] }
function add(x,y) { return x + y }
function tail(list) { return function() { return list()[1]() }}
function zipWith(f, x, y) { return function() {
return [ f(head(x), head(y)),
zipWith(f, tail(x), tail(y))] } }
function runList(list, n) { while(n --> 0) {
console.log(head(list)); list = tail(list)}}</code></pre>
<p>The main difference between a normal recursive definition and this one is that the recursion happens at the value level, as opposed to the function-call location.</p>
<pre class="instruction"><code>
Implement an infinite list of ascending numbers using lazy,
value-based recursion.</code></pre>
<pre class="answer" data-language="haskell" data-filter="resources/scripts/check.sh"><code>ascending = 1 : zipWith (+) ascending ascending
</code></pre>
<pre class="open"><code>An open-ended question:
Can all numeric-lists be defined by using value-based recursion?</code></pre>
</div>
</div>
<div class='chapter'>
<div class='content'>
<h1 id="typeclasses">Type Classes</h1>
<p>A big part of writing clean reusable code is controlled polymorphism. We are like a carny at the roller-coaster, anybody can ride the roller coaster, but you must be at least this tall.</p>
<p>In the object oriented world we use the inheritance heirachy, we know that if something is a subclass, it has at least all of the features of its parent. Of course this is all intertwined with the sharing of data and state, and that's bad.</p>
<p>In the functional world we get type classes, which is just controlled polymorphism without the baggage. They basically say, that I don't need to know exactly what type you'll call me with but you need to provide a bunch of functions for me to use.</p>
<p>A function tells you what type classes it needs with a "context", The context is the bit to the left of the double arrow "=>"</p>
<pre class="nocheck" data-language="haskell"><code>(+) :: Num a => a -> a -> a
show :: Show a => a -> String</code></pre>
<p>In the above example, we have <code>(+)</code>. It can work for any type that is a number. There are built in types for numbers and you can also define your own.</p>
<p><code>show</code> can turn any "Showable" type into a string. this is analogous to the <code>toString()</code> method in Java.</p>
<pre class="instruction"><code>Define a function that adds one to everything in a list.
What is the type of this function?</code></pre>
<pre class="nocheck" data-language="haskell"><code>read :: Read a => String -> a
incrementAndshow :: (Num a, Show a) => a -> String</code></pre>
<p>Unlike most other languages, with some kind of type driven function dispatch (e.g. methods, overloading). Haskell can also use the <em>return</em> type of the function to choose functionality, this can take a little getting used to, but it is powerful.</p>
<p><code>read</code> turns a string into a value of another type, although we don't know what this is yet. It depends, for example on the type of the function that you are passing the result of read into.</p>
<p><code>incrementAndShow</code> demonstrates a function that uses two type classes in its context.</p>
<pre class="instruction"><code>In ghci, convert a string to an integer using read, then covert
a string into a list of integers using read.
(Hint: use (::) to add a type to an expression)
If you just type 'read "1"' in ghci you get an
error, why is this?</code></pre>
<pre class="instruction"><code>Define `incrementAndShow` which adds one to a number and
coverts it to a string.
What is they type of this function?
How did haskell infer your context?</code></pre>
<h1 id="defining-your-own-type-classes">Defining Your Own Type Classes</h1>
<p>Let's define a type class of things that can be rated, as in 1 to 5 stars or awesome to lame.</p>
<pre data-language="haskell" data-filter="./resources/scripts/check.sh"><code>
data Rating =
SoAwesomeICried |
PrettyCool |
Meh |
ForTheLoveOfGodMakeItEnd
deriving Show
class Rateable r where
rating :: r -> Rating
data Beer = Coopers | Fosters | CarltonDraught
deriving Show
instance Rateable Beer where
rating Coopers = PrettyCool
rating Fosters = ForTheLoveOfGodMakeItEnd
rating CarltonDraught = Meh
data Movie = Movie String
deriving Show
instance Rateable Movie where