https://wiki.haskell.org/api.php?action=feedcontributions&user=Wizzup&feedformat=atomHaskellWiki - User contributions [en]2020-11-30T05:53:15ZUser contributionsMediaWiki 1.27.4https://wiki.haskell.org/index.php?title=Online_judges&diff=63108Online judges2019-11-01T10:35:25Z<p>Wizzup: update compiler versions</p>
<hr />
<div>Among many [https://en.wikipedia.org/wiki/Online_judge Online judges] and competitive coding sites there are some that support Haskell, listed in following table.<br />
<br />
{| class="wikitable"<br />
|-<br />
! Site !! GHC version<br />
|-<br />
| [https://www.hackerrank.com HackerRank ] || [https://www.hackerrank.com/environment 8.6.3]<br />
|-<br />
| [https://open.kattis.com Kattis ] || [https://open.kattis.com/help/haskell 8.4.4]<br />
|-<br />
| [https://www.codingame.com CodinGame ] || [https://www.codingame.com/faq 8.4.3]<br />
|-<br />
| [https://www.codewars.com CodeWars ] || [https://github.com/Codewars/codewars.com/wiki/Language-Haskell 8.2.2]<br />
|-<br />
| [https://www.codechef.com CodeChef ] || [https://www.codechef.com/ide 8.0.1]<br />
|-<br />
| [http://codeforces.com CodeForces ] || 7.8.3<br />
|-<br />
| [https://www.hackerearth.com HackerEarth ] || [https://www.hackerearth.com/docs/wiki/developers/judge 7.6.3]<br />
|-<br />
| [https://codefights.com CodeFights ] || 7.6.3<br />
|-<br />
| [http://www.devdraft.com devdraft ] || 7.6<br />
|-<br />
| [http://exercism.io exercism.io ] || Multiple version (using stack)<br />
|-<br />
| [http://codeabbey.com codeabbey ] || (unknown)<br />
|-<br />
| [http://www.edufyme.com edufyme ] || (unknown)<br />
|-<br />
<!-- | [https://www.codeeval.com CodeEval ] || Broken --><br />
<!-- | [https://www.riddles.io Riddles.io ] || [https://playground.riddles.io/competitions/light-riders/how-to-play 7.10.3] (Broken) --><br />
<!-- | [http://theaigames.com TheAIGame ] || 7.10 (defunct) --><br />
|}</div>Wizzuphttps://wiki.haskell.org/index.php?title=Import&diff=62817Import2019-03-14T03:14:06Z<p>Wizzup: /* See also */</p>
<hr />
<div>[[Category:Language]]<br />
[[Category:Glossary]]<br />
The <hask>import</hask> statement is used to import functions and other definitions from another module. The shortest form of the import statement is<br />
<haskell><br />
import Data.Maybe<br />
</haskell><br />
that imports the named module (in this case <hask>Data.Maybe</hask>).<br />
<br />
However, there are more options:<br />
<br />
# Modules can be imported '''qualified''' (forcing an obligatory namespace qualifier to imported identifiers).<br />
# Some identifiers can be skipped via the '''hiding''' clause.<br />
# The module namespace can be renamed, with an '''as''' clause.<br />
<br />
Getting all of this straight in your head is quite tricky, so here is a table (lifted directly from the language reference manual) that roughly summarises the various possibilities: <br />
<br />
Supposing that the module <hask>Mod</hask> exports three functions named <hask>x</hask>, <hask>y</hask> and <hask>z</hask>...<br />
<br />
{|<br />
|-<br />
! Import command<br />
! What is brought into scope<br />
! Notes<br />
|-<br />
| <hask>import Mod</hask><br />
| <hask>x, y, z, Mod.x, Mod.y, Mod.z</hask><br />
| (By default, qualified ''and'' unqualified names.)<br />
|-<br />
| <hask>import Mod ()</hask><br />
| (Nothing!)<br />
| (Useful for only importing instances of typeclasses and nothing else)<br />
|-<br />
| <hask>import Mod (x,y)</hask><br />
| <hask>x, y, Mod.x, Mod.y</hask><br />
| (Only <hask>x</hask> and <hask>y</hask>, no <hask>z</hask>.)<br />
|-<br />
| <hask>import qualified Mod</hask><br />
| <hask>Mod.x, Mod.y, Mod.z</hask><br />
| (Only qualified versions; no unqualified versions.)<br />
|-<br />
| <hask>import qualified Mod (x,y)</hask><br />
| <hask>Mod.x, Mod.y</hask><br />
| (Only <hask>x</hask> and <hask>y</hask>, only qualified.)<br />
|-<br />
| <hask>import Mod hiding (x,y)</hask><br />
| <hask>z, Mod.z</hask><br />
| (<hask>x</hask> and <hask>y</hask> are hidden.)<br />
|-<br />
| <hask>import qualified Mod hiding (x,y)</hask><br />
| <hask>Mod.z</hask><br />
| (<hask>x</hask> and <hask>y</hask> are hidden.)<br />
|-<br />
| <hask>import Mod as Foo</hask><br />
| <hask>x, y, z, Foo.x, Foo.y, Foo.z</hask><br />
| (Unqualified names as before. Qualified names use <hask>Foo</hask> instead of <hask>Mod</hask>.)<br />
|-<br />
| <hask>import Mod as Foo (x,y)</hask><br />
| <hask>x, y, Foo.x, Foo.y</hask><br />
| (Only import <hask>x</hask> and <hask>y</hask>.)<br />
|-<br />
| <hask>import qualified Mod as Foo</hask><br />
| <hask>Foo.x, Foo.y, Foo.z</hask><br />
| (Only qualified names, using new qualifier.)<br />
|-<br />
| <hask>import qualified Mod as Foo (x,y)</hask><br />
| <hask>Foo.x, Foo.y</hask><br />
| (Only qualified versions of <hask>x</hask> and <hask>y</hask>, using new qualifier)<br />
|}<br />
<br />
Note that multiple import statements for the same module are also allowed, so it is possible to mix and match styles if its so desired (for example, importing operators directly and functions qualified)<br />
<br />
===Hiding Prelude===<br />
<br />
By default, ''every module'' implicitly imports <hask>Prelude</hask>. However, if you add an ''explicit'' import declaration for the prelude, this turns off the implicit one. Thus, if you wanted (for example) to write a module that redefines <hask>zip</hask> you could do<br />
<haskell><br />
module Mod where<br />
<br />
import Prelude hiding (zip)<br />
<br />
zip = {- ... -}<br />
</haskell><br />
Without the <hask>import</hask> statement, you could receive a compile-time error about an 'ambiguous use of <hask>zip</hask>'. A slightly more messy alternative is to do<br />
<haskell><br />
module Mod where<br />
<br />
import qualified Prelude as P<br />
<br />
zip = {- ... -}<br />
</haskell><br />
This has the disadvantage that (say) '<hask>P.show (2 P.+ 3 P.* 3) P.++ "abc"</hask>' is very messy to read. Typically a module only redefines a few prelude functions, and it's simpler to just hide the ones you don't want to clash with.<br />
<br />
Note that any module ''using'' a module that redefines prelude functions will need to import either the prelude or the other module (or maybe both) qualified and/or with hiding for the same reason.<br />
<br />
== See also ==<br />
<br />
* [[Import modules properly]] - Some thoughts that may help to decide what form of the import statement to use.<br />
<br />
* [https://downloads.haskell.org/~ghc/latest/docs/html/users_guide/glasgow_exts.html#package-qualified-imports PackageImports] GHC's [[Language_extensions | extensions]] to allow the use of package-qualified import syntax.</div>Wizzuphttps://wiki.haskell.org/index.php?title=User_groups&diff=62815User groups2019-03-11T23:10:55Z<p>Wizzup: /* Online communities */</p>
<hr />
<div>[[Category:Community]]<br />
<br />
A range of Haskell User Groups are springing up all over.<br />
<br />
== Online communities ==<br />
<br />
* Official [https://discourse.haskell.org/ discourse] forum<br />
<br />
* [https://discordapp.com/channels/280033776820813825 discord] <em>Haskell</em> subchannel on <em>Functional Programming</em> channel<br />
<br />
=== Reddit ===<br />
* [https://www.reddit.com/r/haskell/ /r/haskell]<br />
* [https://www.reddit.com/r/haskellgamedev /r/haskellgamedev]<br />
* [https://www.reddit.com/r/haskelltil /r/haskelltil]<br />
* [https://www.reddit.com/r/haskellquestions /r/haskellquestions]<br />
<br />
=== Facebook Groups ===<br />
* [https://www.facebook.com/groups/programming.haskell Programming Haskell]<br />
* [https://www.facebook.com/groups/learning.haskell Learning Haskell]<br />
<br />
=== Google+ communities ===<br />
(Google+ is scheduled for shutdown on April 2, 2019)<br />
<br />
* [https://plus.google.com/communities/101629034466170191725 Haskell: The Haskell-Beginners Community]<br />
* [https://plus.google.com/communities/104818126031270146189 Haskell]<br />
<br />
<br />
* Questions tagged <em>haskell</em> on [https://stackoverflow.com/questions/tagged?tagnames=haskell StackOverflow]<br />
<br />
== User groups ==<br />
<br />
Regular meetings in a particular geographical area. Great if you want to see and meet other Haskellers.<br />
<br />
<br />
===Africa===<br />
<br />
====South Africa====<br />
; [http://www.meetup.com/lambda-luminaries/ Lambda Luminaries] : Functional programming user group based in Centurion, Gauteng.<br />
<br />
===Asia===<br />
<br />
====China====<br />
;[http://lisp.org.cn/en/ China Lisp User Group]<br />
:China Lisp User Group (CLUG) is the earliest founded Lisp user group in China. <br />
<br />
====Hong Kong====<br />
;[http://www.meetup.com/HK-Functional-programming/ Hong Kong Functional Programming User Meetup Group]<br />
<br />
====India====<br />
;[https://t.me/haskellindia Haskell India Group]<br />
: Telegram group that complements existing personal meetups at various places in India. To join, go here on your mobile browser: https://t.me/haskellindia<br />
<br />
;[https://www.meetup.com/The-Bangalore-Haskell-User-Group/ The Bangalore Haskell User Group]<br />
: We are a diverse group of experienced Haskellers, commercial Haskell users as well as learners, meeting up at Bangalore usually on Saturdays at 3:00 PM - 5:00 PM.<br />
<br />
====Japan====<br />
;[https://haskell.jp/ Japan Haskell Users Group (Haskell-jp)]<br />
:blog, slack, recipes, events (meetings) and more<br />
<br />
;[http://www.starling-software.com/en/tsac.html Tokyo Society for the Application of Currying]<br />
<br />
;[http://www.meetup.com/Tokyo-Haskell-Meetup/ Tokyo Haskell Meetup]<br />
:Casual monthly meetings to help each other learn Haskell<br />
<br />
====Singapore====<br />
;[https://www.meetup.com/HASKELL-SG HASKELL.SG Meetup]<br />
<br />
===Europe===<br />
<br />
==== Belgium ====<br />
<br />
;[[Ghent Functional Programming Group]]<br />
:The Ghent Functional Programming Group will be having its first meeting on April 1, 2010.<br />
<br />
;[https://groups.google.com/forum/#!forum/leuven-haskell Leuven Haskell User Group]<br />
:The Leuven Haskell User Group was launched on March 3, 2015 and meets every two weeks.<br />
<br />
==== Czech Republic ====<br />
<br />
;[https://fpbrno.github.io Functional Programming Brno]<br />
<br />
==== France ====<br />
<br />
;[[Fr/Haskell]]<br />
:The Strasbourg HUG meets monthly in an informal setting. Level is very low and newbies are very welcome.<br />
<br />
==== Germany ====<br />
<br />
;Curry Club Augsburg<br />
:http://curry-club-augsburg.de/<br />
<br />
;Berlin HUG<br />
:http://www.meetup.com/berlinhug/<br />
<br />
;Haskell in Frankfurt<br />
: <ul><li>[http://www.meetup.com/Frankfurt-Haskell-User-Group Frankfurt Haskell User Group] meets monthly.</li><li> [http://wiki.lug-frankfurt.de/Programmierworkshop/aktuell Regular Saturday Workshop] taking place every couple of months. Feel free to join us!</li><br />
<br />
;[http://www.iba-cg.de/hal5.html Haskell in Leipzig]<br />
:Hal, they have videos [http://iba-cg.de/haskell.html online].<br />
<br />
;[http://www.haskell-munich.de Haskell in Munich]<br />
: We had our first meeting on Thursday, 29th of September 2011. We are always looking forward to see new people. If you can make it to Munich, consider joing us!<br />
<br />
;[http://www.meetup.com/de-DE/Regensburg-Haskell-Meetup Regensburg Haskell Meetup]<br />
: We meet regularly once a month since 2014. Folks from the Munich and Nuremberg area frequently join.<br />
<br />
;Interest for User Groups in Germany<br />
* '''Ulm''': [[HugUlm]]<br />
* '''Mannheim or Heidelberg''': [[User:Cgo|cgo]] ([http://www.haskell.org/haskellwiki/?title=Special:Emailuser&target=Cgo mail]), [[User:HC|hc]]<br />
<br />
==== Greece ====<br />
<br />
;[https://groups.google.com/forum/#!forum/haskell-greece/ Haskell Greece Google group]<br />
<br />
==== Hungary ====<br />
<br />
;[http://www.meetup.com/Bp-HUG Budapest Haskell User Group]<br />
:The Haskell User Group is a group of Haskell enthusiasts who are interested in sharing their knowledge and meeting people who share similar interests. We had our first meeting in September 2013.<br />
<br />
==== Iceland ====<br />
<br />
;[[Reykjavik Haskell User Group]] Iceland<br />
;[http://groups.google.com/group/haskell-is Currently recruiting members]<br />
<br />
==== Israel ====<br />
<br />
;[[IsraelHaskell]] User Group<br />
:[http://article.gmane.org/gmane.comp.lang.haskell.cafe/28877 Are getting organised].<br />
* '''Konstanz''': [[User:Thkoch|thkoch]]<br />
<br />
==== Italy ====<br />
;[[ItaloHaskell]]<br />
:We had a first meeting in August 2008 and we are planning a second one sometime during the 2008/2009 Autumn/Winter season.<br />
<br />
==== Netherlands ====<br />
<br />
;[http://dutchhug.nl/ Dutch HUG]<br />
:The Dutch HUG meets monthly in an informal setting.<br />
<br />
==== Norway ====<br />
<br />
;[http://www.meetup.com/Oslo-Haskell/ Osλo Haskell]<br />
:Osλo Haskell is a group for Haskellers and people interested in Haskell and related languages in and around Oslo. We had our first meeting in March 2014.<br />
<br />
;[http://www.meetup.com/Trondheim-Haskell-Users-Group/ Trondheim Haskell Users' Group]<br />
:A Haskell users' group in the Trondheim area. For seasoned veterans, complete newbies who only heard of Haskell two minutes ago, and everyone in between and beyond. We meet and talk about Haskell and anything else members are interested in.<br />
<br />
==== Poland ====<br />
;[https://plus.google.com/u/0/communities/103183708602453146804 HUG Warsaw] <br />
We are the successors to the Warsaw Functional Society (Warszawskie Towarzystwo Funkcyjne) and as such we welcome any functional programmers and enthusiasts, though the focus of the group is Haskell. We (hope to) have rather informal, but regular meetings in Warsaw, Poland.<br />
<br />
==== Russia ====<br />
<br />
;[http://ruhaskell.org/ Russian community of Haskell-developers]<br />
;[http://spbhug.folding-maps.org Saint-Petersburg Haskell User Group]<br />
;[https://groups.google.com/forum/#!forum/mskhug Moscow Haskell User Group]<br />
;[https://groups.google.com/forum/#!aboutgroup/haskell-russian haskell-russian mailing list]<br />
<br />
==== Switzerland ====<br />
<br />
;[http://www.meetup.com/HaskellerZ/ Haskell User Group Zurich]<br />
:We are meeting once a month to share knowledge of and experience with Haskell.<br />
<br />
;[http://www.meetup.com/Geneva-Haskell-Group/ Geneva Haskell Group]<br />
:We are a Haskell community in Geneva planning to meet up every week.<br />
<br />
==== Turkey ====<br />
<br />
;[http://groups.google.com/group/core-haskell?lnk=srg Turkey Haskell Programmer's Group]<br />
:Formed by Turkish Functional Programmers, the group began to communicate via an e-mail list opened by core.gen.tr. The first contribution is hlibev project by Aycan iRiCAN.<br />
<br />
;[http://bilfp.wikidot.com/ BILFP (Bilkent University Comp. Eng. Dept. Functional Programming Society)] Turkey <br />
:Project aims to improve people's knowledge and encourage the use of functional programming languages &mdash; especially in Turkey. Group is open to functional-programming-related discussions and establishes related presentations at Bilkent University that are open to anybody.<br />
<br />
==== UK ====<br />
;[http://lambdalounge.org.uk/ Manchester Lambda Lounge]<br />
:We are an active community meeting monthly at the [http://madlab.org.uk/ Madlab] (Manchester Digital Laboratory) to talk about topics in functional programming.<br />
<br />
;[http://www.meetup.com/hoodlums/ Hoodlums - Haskell developer meetup]<br />
:Meets monthly on the second Thursday of the month in Canary Wharf. It is a "Coding Dojo" format where we pick some interesting problem and solve it as a group. <br />
<br />
;[http://www.meetup.com/London-HUG/ London Haskell User Group]<br />
:The main meetings are monthly on the last or fourth Thursday of the month. The group was revived in late 2012.<br />
<br />
;[http://www.meetup.com/ed-lambda/ ed lambda (Edinburgh, UK)]<br />
:For functional programming in general, founded by a Haskeller. First meeting will be September 13th 2010.<br />
<br />
;[http://groups.google.com/group/oxhug OxHUG - the Oxford Haskell Users Group]<br />
:Meets every other week, currently at the Department of Computer Science, University of Oxford. Discussion session followed by adjournment to a local tavern. Aimed at students, graduates, professionals and enthusiasts.<br />
<br />
;[http://groups.google.com/group/fp-southwales fp-southwales], the South Wales Functional Programming User Group<br />
:Starting up in late 2009, based out of Swansea University.<br />
<br />
==== Ukraine ====<br />
;[https://groups.google.com/forum/#!forum/ltu-kiev LtU-Kiev community]<br />
:Irregular meetups, usually with prepared talks on Haskell and other FP topics.<br />
;[http://www.haskell.od.ua Odessa Haskell User Group]<br />
:Regular informal meetups (approximately once a month) in a pub or cafe<br />
<br />
===North America===<br />
<br />
====Central====<br />
<br />
;[http://leibnizdream.wordpress.com/2007/12/22/new-austin-functional-programmers-group-in-2008/ Austin Functional Programmers Group]<br />
:See the [http://groups.google.com/group/austin-fp discussion group] for more.<br />
<br />
;[http://www.meetup.com/Boulder-Haskell-Programmers/ Boulder Haskell Programmers]<br />
: Boulder and Denver (Colorado) area Haskell Programmer Group. Meetings are focused on practical topics faced by working programmers. All experience levels are welcome.<br />
<br />
;[http://groups.google.com/group/real-world-haskell-book-club/browse_thread/thread/3e8e59768c8c50a9 Colorado Area Haskell Study Group]<br />
<br />
;[http://ChicagoHaskell.com Chicago Haskell] — First general meeting in December 2009. — [https://groups.google.com/forum/#!forum/haskell-chicago Mailing List] — [https://twitter.com/ChicagoHaskell @ChicagoHaskell]<br />
<br />
;[http://www.meetup.com/DenHUG/ Denver Area Haskell Users Group] -- DenHUG had it's first meeting on 27 Feb 2010. Next meeting will be 3 Apr 2010.<br />
<br />
;[http://www.meetup.com/Houston-Haskell-Users-Group/ Houston Haskell Users Group] -- Meets the 1st Monday of every month at [https://txrxlabs.org/ TxRx labs]<br />
<br />
;[http://www.lambdalounge.org St. Louis Lambda Lounge] -- Meets the 1st Thursday of the month. Since Dec 2008, Lambda Lounge is a user group in St. Louis organized loosely around the idea of exploring dynamic and functional languages.<br />
<br />
;[http://www.meetup.com/Nashville-Haskell-Users-Group Nashville Haskell Users Group (NHUG)] -- Meets 1st Tuesday of each month.<br />
<br />
====East Coast====<br />
<br />
;[http://groups.google.com/group/bostonhaskell Boston Haskell Users' Group].<br />
:Meets monthly.<br />
<br />
;[http://www.meetup.com/NY-Haskell/ New York Haskell Users Group]<br />
:The NY Haskell Users Group is for all programmers either interested in or experienced with the Haskell programming language. Meets monthly.<br />
<br />
;[http://www.meetup.com/lisp-59/ New York Functional Programmers]<br />
:Come and meet like-minded functional programmers in the New York area.<br />
<br />
;[http://www.meetup.com/Haskell-DC/ Haskell DC]<br />
:Washington DC area Meetup for Haskell.<br />
<br />
;[http://www.lisperati.com/fringedc.html FringeDC Washington]<br />
:Meetings about functional programming languages in Washington DC.<br />
<br />
;[http://groups.google.com/group/AFPUG Atlanta Functional Programming Users Group]<br />
:Meet other functional programmers in the Atlanta area. Join us and geek out!<br />
<br />
;Toronto Haskell User Group<br />
:Haskellers of Toronto, unite! We meet at [https://bentomiso.com/events Bento Miso] on the second Wednesday of every month (check the [https://bentomiso.com/events event page] to be sure; it's usually up-to-date). There is also a small organizational [http://groups.google.com/group/toronto-haskell/ mailing list] you can join to keep up to date.<br />
<br />
;Toronto Haskell Meetup<br />
:A beginner friendly place to learn about Haskell, ask questions, and meet friendly FP enthusiasts - [https://www.meetup.com/meetup-group-evRITRtT/ you can find us on meetup.com]<br />
<br />
;[http://www.haskellers-montreal.com/ Haskellers Montreal Group].<br />
:Meets every 2 months on the first Wednesday of that month, currently at Centre [http://cloud.ca Cloud.ca] (previously known as RPM). Talks alternate from expert-level to more newcomer-oriented ones; and we organize through our [http://haskell-meetup.sandreckoning.com/ website], a [https://groups.google.com/forum/#!forum/haskellers-montreal Google group] and a [http://www.meetup.com/Haskellers-Montreal-Meetup/ meetup.com] page.<br />
<br />
====West Coast ====<br />
<br />
;[http://socalfp.blogspot.com/ SoCal FP Group]<br />
<br />
;[http://www.meetup.com/sandiegohug/ San Diego Haskell User Group]<br />
:a Haskell User Group for the San Diego and Tijuana region<br />
<br />
;[http://bayfp.org/ The Bay Area Functional Programmers group]<br />
:Meeting monthly in the San Francisco Bay area. See [http://bayfp.org/blog their blog] for more details and news of upcoming meetings.<br />
<br />
;[http://pdxfunc.org PDXfunc: Portland FP Group]<br />
:Monthly meetings of the Portland, Oregon functional programming group. Meetings occur on the second Monday of each month at 7 pm, typically in Downtown/NW Portland.<br />
<br />
;[http://seattlehaskell.org/ Seattle Area Haskell Users' Group]<br />
:Monthly get-togethers serving Seattle and the Eastside (see also [http://meetup.com/SEAHUG/ Meetup.com] for details)<br />
<br />
;[http://www.haskell.org/pipermail/haskell-cafe/2008-February/038991.html Seattle: Northwest Functional Programming Interest Group]<br />
:a Northwest Functional Programming Interest Group in Seattle.<br />
<br />
;[http://www.meetup.com/Vancouver-Haskell-Unmeetup/ Vancouver Haskell UnMeetup]<br />
:Monthly interactive sessions, (+10) for joining<br />
<br />
===Oceania===<br />
====Australia====<br />
<br />
;[http://groups.google.com/group/fp-syd FP-SYD, the Sydney (Australia) Functional Programming group]<br />
:FP hackers in Sydney.<br />
<br />
;[http://sites.google.com/site/fpunion/ (FPU) Melbourne Functional Programming Union]<br />
:The FPU is a collective of functional programming language enthusiasts, which has been in operation since 1998. We are based at the University of Melbourne, in the Department of Computer Science and Software Engineering, but we are open to all members of the community. We meet on a regular basis for lively discussions on topics broadly associated with the declarative programming paradigm.<br />
<br />
;[http://bfpg.org/ Brisbane Functional Programming Group (BFPG)] ([http://www.meetup.com/Brisbane-Functional-Programming-Group-BFG/ Meetup page])<br />
:A group for Functional Programming with Haskell, Scala and other languages.<br />
<br />
;[http://meetup.com/PerthFP/ Perth Functional Programmers Meetup]<br />
:A group in Perth, WA for Functional Programming with Haskell, Scala and other languages.<br />
<br />
===South America===<br />
<br />
==== Bolivia ====<br />
; [https://www.facebook.com/groups/111518795538430/ Comunidad Haskell San Simon (CHSS)]<br />
: Haskell user group for Bolivia and spanish speaking community<br />
<br />
====Brazil====<br />
;[[User_groups/Brazil|Grupo Brasileiro de Usuários de Haskell]]<br />
: Grupo criado para reunir os desenvolvedores e entusiastas que utilizam Haskell no Brasil<br />
<br />
====Ecuador====<br />
; [http://www.meetup.com/Quito-Lambda-Meetup/ Quito Lambda]<br />
: A monthly meetup about functional programming in Quito, Ecuador<br />
<br />
== Workshops/meet ups ==<br />
<br />
Less regular, and move around. Usually have a few talks from invited speakers.<br />
See the [[Haskell]] homepage for a list of upcoming events.<br />
<br />
== Hackathons ==<br />
<br />
Getting together to squash bugs and write new stuff. For a list of past and upcoming hackathons, see the [[Hackathon]] page.<br />
<br />
== Conferences ==<br />
<br />
See the [[Haskell_in_research#Conferences|Haskell in research]] and [[Conferences]] page for academic workshops and conferences<br />
focusing on Haskell and related technology.</div>Wizzuphttps://wiki.haskell.org/index.php?title=User_groups&diff=62814User groups2019-03-11T23:01:44Z<p>Wizzup: /* Online communities */ Add links</p>
<hr />
<div>[[Category:Community]]<br />
<br />
A range of Haskell User Groups are springing up all over.<br />
<br />
== Online communities ==<br />
<br />
=== Reddit ===<br />
* [https://www.reddit.com/r/haskell/ /r/haskell]<br />
* [https://www.reddit.com/r/haskellgamedev /r/haskellgamedev]<br />
* [https://www.reddit.com/r/haskelltil /r/haskelltil]<br />
* [https://www.reddit.com/r/haskellquestions /r/haskellquestions]<br />
<br />
=== Facebook Groups ===<br />
* [https://www.facebook.com/groups/programming.haskell Programming Haskell]<br />
* [https://www.facebook.com/groups/learning.haskell Learning Haskell]<br />
<br />
=== Google+ communities ===<br />
(Google+ is scheduled for shutdown on April 2, 2019)<br />
<br />
* [https://plus.google.com/communities/101629034466170191725 Haskell: The Haskell-Beginners Community]<br />
* [https://plus.google.com/communities/104818126031270146189 Haskell]<br />
<br />
<br />
<br />
* [https://stackoverflow.com/questions/tagged?tagnames=haskell Stack Overflow (#haskell)]<br />
<br />
* [https://discourse.haskell.org/ discourse]<br />
<br />
* [https://discordapp.com/channels/280033776820813825 discord]<br />
<br />
== User groups ==<br />
<br />
Regular meetings in a particular geographical area. Great if you want to see and meet other Haskellers.<br />
<br />
<br />
===Africa===<br />
<br />
====South Africa====<br />
; [http://www.meetup.com/lambda-luminaries/ Lambda Luminaries] : Functional programming user group based in Centurion, Gauteng.<br />
<br />
===Asia===<br />
<br />
====China====<br />
;[http://lisp.org.cn/en/ China Lisp User Group]<br />
:China Lisp User Group (CLUG) is the earliest founded Lisp user group in China. <br />
<br />
====Hong Kong====<br />
;[http://www.meetup.com/HK-Functional-programming/ Hong Kong Functional Programming User Meetup Group]<br />
<br />
====India====<br />
;[https://t.me/haskellindia Haskell India Group]<br />
: Telegram group that complements existing personal meetups at various places in India. To join, go here on your mobile browser: https://t.me/haskellindia<br />
<br />
;[https://www.meetup.com/The-Bangalore-Haskell-User-Group/ The Bangalore Haskell User Group]<br />
: We are a diverse group of experienced Haskellers, commercial Haskell users as well as learners, meeting up at Bangalore usually on Saturdays at 3:00 PM - 5:00 PM.<br />
<br />
====Japan====<br />
;[https://haskell.jp/ Japan Haskell Users Group (Haskell-jp)]<br />
:blog, slack, recipes, events (meetings) and more<br />
<br />
;[http://www.starling-software.com/en/tsac.html Tokyo Society for the Application of Currying]<br />
<br />
;[http://www.meetup.com/Tokyo-Haskell-Meetup/ Tokyo Haskell Meetup]<br />
:Casual monthly meetings to help each other learn Haskell<br />
<br />
====Singapore====<br />
;[https://www.meetup.com/HASKELL-SG HASKELL.SG Meetup]<br />
<br />
===Europe===<br />
<br />
==== Belgium ====<br />
<br />
;[[Ghent Functional Programming Group]]<br />
:The Ghent Functional Programming Group will be having its first meeting on April 1, 2010.<br />
<br />
;[https://groups.google.com/forum/#!forum/leuven-haskell Leuven Haskell User Group]<br />
:The Leuven Haskell User Group was launched on March 3, 2015 and meets every two weeks.<br />
<br />
==== Czech Republic ====<br />
<br />
;[https://fpbrno.github.io Functional Programming Brno]<br />
<br />
==== France ====<br />
<br />
;[[Fr/Haskell]]<br />
:The Strasbourg HUG meets monthly in an informal setting. Level is very low and newbies are very welcome.<br />
<br />
==== Germany ====<br />
<br />
;Curry Club Augsburg<br />
:http://curry-club-augsburg.de/<br />
<br />
;Berlin HUG<br />
:http://www.meetup.com/berlinhug/<br />
<br />
;Haskell in Frankfurt<br />
: <ul><li>[http://www.meetup.com/Frankfurt-Haskell-User-Group Frankfurt Haskell User Group] meets monthly.</li><li> [http://wiki.lug-frankfurt.de/Programmierworkshop/aktuell Regular Saturday Workshop] taking place every couple of months. Feel free to join us!</li><br />
<br />
;[http://www.iba-cg.de/hal5.html Haskell in Leipzig]<br />
:Hal, they have videos [http://iba-cg.de/haskell.html online].<br />
<br />
;[http://www.haskell-munich.de Haskell in Munich]<br />
: We had our first meeting on Thursday, 29th of September 2011. We are always looking forward to see new people. If you can make it to Munich, consider joing us!<br />
<br />
;[http://www.meetup.com/de-DE/Regensburg-Haskell-Meetup Regensburg Haskell Meetup]<br />
: We meet regularly once a month since 2014. Folks from the Munich and Nuremberg area frequently join.<br />
<br />
;Interest for User Groups in Germany<br />
* '''Ulm''': [[HugUlm]]<br />
* '''Mannheim or Heidelberg''': [[User:Cgo|cgo]] ([http://www.haskell.org/haskellwiki/?title=Special:Emailuser&target=Cgo mail]), [[User:HC|hc]]<br />
<br />
==== Greece ====<br />
<br />
;[https://groups.google.com/forum/#!forum/haskell-greece/ Haskell Greece Google group]<br />
<br />
==== Hungary ====<br />
<br />
;[http://www.meetup.com/Bp-HUG Budapest Haskell User Group]<br />
:The Haskell User Group is a group of Haskell enthusiasts who are interested in sharing their knowledge and meeting people who share similar interests. We had our first meeting in September 2013.<br />
<br />
==== Iceland ====<br />
<br />
;[[Reykjavik Haskell User Group]] Iceland<br />
;[http://groups.google.com/group/haskell-is Currently recruiting members]<br />
<br />
==== Israel ====<br />
<br />
;[[IsraelHaskell]] User Group<br />
:[http://article.gmane.org/gmane.comp.lang.haskell.cafe/28877 Are getting organised].<br />
* '''Konstanz''': [[User:Thkoch|thkoch]]<br />
<br />
==== Italy ====<br />
;[[ItaloHaskell]]<br />
:We had a first meeting in August 2008 and we are planning a second one sometime during the 2008/2009 Autumn/Winter season.<br />
<br />
==== Netherlands ====<br />
<br />
;[http://dutchhug.nl/ Dutch HUG]<br />
:The Dutch HUG meets monthly in an informal setting.<br />
<br />
==== Norway ====<br />
<br />
;[http://www.meetup.com/Oslo-Haskell/ Osλo Haskell]<br />
:Osλo Haskell is a group for Haskellers and people interested in Haskell and related languages in and around Oslo. We had our first meeting in March 2014.<br />
<br />
;[http://www.meetup.com/Trondheim-Haskell-Users-Group/ Trondheim Haskell Users' Group]<br />
:A Haskell users' group in the Trondheim area. For seasoned veterans, complete newbies who only heard of Haskell two minutes ago, and everyone in between and beyond. We meet and talk about Haskell and anything else members are interested in.<br />
<br />
==== Poland ====<br />
;[https://plus.google.com/u/0/communities/103183708602453146804 HUG Warsaw] <br />
We are the successors to the Warsaw Functional Society (Warszawskie Towarzystwo Funkcyjne) and as such we welcome any functional programmers and enthusiasts, though the focus of the group is Haskell. We (hope to) have rather informal, but regular meetings in Warsaw, Poland.<br />
<br />
==== Russia ====<br />
<br />
;[http://ruhaskell.org/ Russian community of Haskell-developers]<br />
;[http://spbhug.folding-maps.org Saint-Petersburg Haskell User Group]<br />
;[https://groups.google.com/forum/#!forum/mskhug Moscow Haskell User Group]<br />
;[https://groups.google.com/forum/#!aboutgroup/haskell-russian haskell-russian mailing list]<br />
<br />
==== Switzerland ====<br />
<br />
;[http://www.meetup.com/HaskellerZ/ Haskell User Group Zurich]<br />
:We are meeting once a month to share knowledge of and experience with Haskell.<br />
<br />
;[http://www.meetup.com/Geneva-Haskell-Group/ Geneva Haskell Group]<br />
:We are a Haskell community in Geneva planning to meet up every week.<br />
<br />
==== Turkey ====<br />
<br />
;[http://groups.google.com/group/core-haskell?lnk=srg Turkey Haskell Programmer's Group]<br />
:Formed by Turkish Functional Programmers, the group began to communicate via an e-mail list opened by core.gen.tr. The first contribution is hlibev project by Aycan iRiCAN.<br />
<br />
;[http://bilfp.wikidot.com/ BILFP (Bilkent University Comp. Eng. Dept. Functional Programming Society)] Turkey <br />
:Project aims to improve people's knowledge and encourage the use of functional programming languages &mdash; especially in Turkey. Group is open to functional-programming-related discussions and establishes related presentations at Bilkent University that are open to anybody.<br />
<br />
==== UK ====<br />
;[http://lambdalounge.org.uk/ Manchester Lambda Lounge]<br />
:We are an active community meeting monthly at the [http://madlab.org.uk/ Madlab] (Manchester Digital Laboratory) to talk about topics in functional programming.<br />
<br />
;[http://www.meetup.com/hoodlums/ Hoodlums - Haskell developer meetup]<br />
:Meets monthly on the second Thursday of the month in Canary Wharf. It is a "Coding Dojo" format where we pick some interesting problem and solve it as a group. <br />
<br />
;[http://www.meetup.com/London-HUG/ London Haskell User Group]<br />
:The main meetings are monthly on the last or fourth Thursday of the month. The group was revived in late 2012.<br />
<br />
;[http://www.meetup.com/ed-lambda/ ed lambda (Edinburgh, UK)]<br />
:For functional programming in general, founded by a Haskeller. First meeting will be September 13th 2010.<br />
<br />
;[http://groups.google.com/group/oxhug OxHUG - the Oxford Haskell Users Group]<br />
:Meets every other week, currently at the Department of Computer Science, University of Oxford. Discussion session followed by adjournment to a local tavern. Aimed at students, graduates, professionals and enthusiasts.<br />
<br />
;[http://groups.google.com/group/fp-southwales fp-southwales], the South Wales Functional Programming User Group<br />
:Starting up in late 2009, based out of Swansea University.<br />
<br />
==== Ukraine ====<br />
;[https://groups.google.com/forum/#!forum/ltu-kiev LtU-Kiev community]<br />
:Irregular meetups, usually with prepared talks on Haskell and other FP topics.<br />
;[http://www.haskell.od.ua Odessa Haskell User Group]<br />
:Regular informal meetups (approximately once a month) in a pub or cafe<br />
<br />
===North America===<br />
<br />
====Central====<br />
<br />
;[http://leibnizdream.wordpress.com/2007/12/22/new-austin-functional-programmers-group-in-2008/ Austin Functional Programmers Group]<br />
:See the [http://groups.google.com/group/austin-fp discussion group] for more.<br />
<br />
;[http://www.meetup.com/Boulder-Haskell-Programmers/ Boulder Haskell Programmers]<br />
: Boulder and Denver (Colorado) area Haskell Programmer Group. Meetings are focused on practical topics faced by working programmers. All experience levels are welcome.<br />
<br />
;[http://groups.google.com/group/real-world-haskell-book-club/browse_thread/thread/3e8e59768c8c50a9 Colorado Area Haskell Study Group]<br />
<br />
;[http://ChicagoHaskell.com Chicago Haskell] — First general meeting in December 2009. — [https://groups.google.com/forum/#!forum/haskell-chicago Mailing List] — [https://twitter.com/ChicagoHaskell @ChicagoHaskell]<br />
<br />
;[http://www.meetup.com/DenHUG/ Denver Area Haskell Users Group] -- DenHUG had it's first meeting on 27 Feb 2010. Next meeting will be 3 Apr 2010.<br />
<br />
;[http://www.meetup.com/Houston-Haskell-Users-Group/ Houston Haskell Users Group] -- Meets the 1st Monday of every month at [https://txrxlabs.org/ TxRx labs]<br />
<br />
;[http://www.lambdalounge.org St. Louis Lambda Lounge] -- Meets the 1st Thursday of the month. Since Dec 2008, Lambda Lounge is a user group in St. Louis organized loosely around the idea of exploring dynamic and functional languages.<br />
<br />
;[http://www.meetup.com/Nashville-Haskell-Users-Group Nashville Haskell Users Group (NHUG)] -- Meets 1st Tuesday of each month.<br />
<br />
====East Coast====<br />
<br />
;[http://groups.google.com/group/bostonhaskell Boston Haskell Users' Group].<br />
:Meets monthly.<br />
<br />
;[http://www.meetup.com/NY-Haskell/ New York Haskell Users Group]<br />
:The NY Haskell Users Group is for all programmers either interested in or experienced with the Haskell programming language. Meets monthly.<br />
<br />
;[http://www.meetup.com/lisp-59/ New York Functional Programmers]<br />
:Come and meet like-minded functional programmers in the New York area.<br />
<br />
;[http://www.meetup.com/Haskell-DC/ Haskell DC]<br />
:Washington DC area Meetup for Haskell.<br />
<br />
;[http://www.lisperati.com/fringedc.html FringeDC Washington]<br />
:Meetings about functional programming languages in Washington DC.<br />
<br />
;[http://groups.google.com/group/AFPUG Atlanta Functional Programming Users Group]<br />
:Meet other functional programmers in the Atlanta area. Join us and geek out!<br />
<br />
;Toronto Haskell User Group<br />
:Haskellers of Toronto, unite! We meet at [https://bentomiso.com/events Bento Miso] on the second Wednesday of every month (check the [https://bentomiso.com/events event page] to be sure; it's usually up-to-date). There is also a small organizational [http://groups.google.com/group/toronto-haskell/ mailing list] you can join to keep up to date.<br />
<br />
;Toronto Haskell Meetup<br />
:A beginner friendly place to learn about Haskell, ask questions, and meet friendly FP enthusiasts - [https://www.meetup.com/meetup-group-evRITRtT/ you can find us on meetup.com]<br />
<br />
;[http://www.haskellers-montreal.com/ Haskellers Montreal Group].<br />
:Meets every 2 months on the first Wednesday of that month, currently at Centre [http://cloud.ca Cloud.ca] (previously known as RPM). Talks alternate from expert-level to more newcomer-oriented ones; and we organize through our [http://haskell-meetup.sandreckoning.com/ website], a [https://groups.google.com/forum/#!forum/haskellers-montreal Google group] and a [http://www.meetup.com/Haskellers-Montreal-Meetup/ meetup.com] page.<br />
<br />
====West Coast ====<br />
<br />
;[http://socalfp.blogspot.com/ SoCal FP Group]<br />
<br />
;[http://www.meetup.com/sandiegohug/ San Diego Haskell User Group]<br />
:a Haskell User Group for the San Diego and Tijuana region<br />
<br />
;[http://bayfp.org/ The Bay Area Functional Programmers group]<br />
:Meeting monthly in the San Francisco Bay area. See [http://bayfp.org/blog their blog] for more details and news of upcoming meetings.<br />
<br />
;[http://pdxfunc.org PDXfunc: Portland FP Group]<br />
:Monthly meetings of the Portland, Oregon functional programming group. Meetings occur on the second Monday of each month at 7 pm, typically in Downtown/NW Portland.<br />
<br />
;[http://seattlehaskell.org/ Seattle Area Haskell Users' Group]<br />
:Monthly get-togethers serving Seattle and the Eastside (see also [http://meetup.com/SEAHUG/ Meetup.com] for details)<br />
<br />
;[http://www.haskell.org/pipermail/haskell-cafe/2008-February/038991.html Seattle: Northwest Functional Programming Interest Group]<br />
:a Northwest Functional Programming Interest Group in Seattle.<br />
<br />
;[http://www.meetup.com/Vancouver-Haskell-Unmeetup/ Vancouver Haskell UnMeetup]<br />
:Monthly interactive sessions, (+10) for joining<br />
<br />
===Oceania===<br />
====Australia====<br />
<br />
;[http://groups.google.com/group/fp-syd FP-SYD, the Sydney (Australia) Functional Programming group]<br />
:FP hackers in Sydney.<br />
<br />
;[http://sites.google.com/site/fpunion/ (FPU) Melbourne Functional Programming Union]<br />
:The FPU is a collective of functional programming language enthusiasts, which has been in operation since 1998. We are based at the University of Melbourne, in the Department of Computer Science and Software Engineering, but we are open to all members of the community. We meet on a regular basis for lively discussions on topics broadly associated with the declarative programming paradigm.<br />
<br />
;[http://bfpg.org/ Brisbane Functional Programming Group (BFPG)] ([http://www.meetup.com/Brisbane-Functional-Programming-Group-BFG/ Meetup page])<br />
:A group for Functional Programming with Haskell, Scala and other languages.<br />
<br />
;[http://meetup.com/PerthFP/ Perth Functional Programmers Meetup]<br />
:A group in Perth, WA for Functional Programming with Haskell, Scala and other languages.<br />
<br />
===South America===<br />
<br />
==== Bolivia ====<br />
; [https://www.facebook.com/groups/111518795538430/ Comunidad Haskell San Simon (CHSS)]<br />
: Haskell user group for Bolivia and spanish speaking community<br />
<br />
====Brazil====<br />
;[[User_groups/Brazil|Grupo Brasileiro de Usuários de Haskell]]<br />
: Grupo criado para reunir os desenvolvedores e entusiastas que utilizam Haskell no Brasil<br />
<br />
====Ecuador====<br />
; [http://www.meetup.com/Quito-Lambda-Meetup/ Quito Lambda]<br />
: A monthly meetup about functional programming in Quito, Ecuador<br />
<br />
== Workshops/meet ups ==<br />
<br />
Less regular, and move around. Usually have a few talks from invited speakers.<br />
See the [[Haskell]] homepage for a list of upcoming events.<br />
<br />
== Hackathons ==<br />
<br />
Getting together to squash bugs and write new stuff. For a list of past and upcoming hackathons, see the [[Hackathon]] page.<br />
<br />
== Conferences ==<br />
<br />
See the [[Haskell_in_research#Conferences|Haskell in research]] and [[Conferences]] page for academic workshops and conferences<br />
focusing on Haskell and related technology.</div>Wizzuphttps://wiki.haskell.org/index.php?title=Programming_guidelines&diff=62805Programming guidelines2019-03-01T08:09:39Z<p>Wizzup: more external guidelines</p>
<hr />
<div>Programming guidelines shall help to make the code of a project better<br />
readable and maintainable by the varying number of contributors.<br />
<br />
It takes some programming experience to develop something like a<br />
personal "coding style" and guidelines only serve as rough shape for<br />
code. Guidelines should be followed by all members working on the<br />
project even if they prefer (or are already used to) different<br />
guidelines.<br />
<br />
These guidelines have been originally set up for the [http://hets.eu hets-project] and are<br />
now put on the [http://haskell.org/haskellwiki/ HaskellWiki] gradually<br />
integrating parts of the old hawiki<br />
entries [http://haskell.org/haskellwiki/Things_to_avoid ThingsToAvoid] and<br />
HaskellStyle (hopefully not<br />
hurting someone's copyrights). The other related entry<br />
TipsAndTricks treats more<br />
specific points that are left out here,<br />
<br />
Surely some style choices are a bit arbitrary (or "religious") and<br />
too restrictive with respect to language extensions. Nevertheless I hope<br />
to keep up these guidelines (at least as a basis) for our project<br />
in order to avoid maintaining diverging guidelines. Of course I want<br />
to supply - partly tool-dependent - reasons for certain decisions and<br />
also show alternatives by possibly bad examples. At the time of<br />
writing I use ghc-6.4.1, haddock-0.7 and (GNU-) emacs with the latest<br />
[http://www.haskell.org/haskell-mode/ haskell mode].<br />
<br />
The following quote and links are taken from<br />
HaskellStyle:<br />
<br />
We all have our own ideas about good Haskell style. There's More Than<br />
One Way To Do It. But some ways are better than others.<br />
<br />
Some comments from the GHC team about their internal coding<br />
standards can be found at<br />
http://hackage.haskell.org/trac/ghc/wiki/WorkingConventions<br />
<br />
Also http://research.microsoft.com/~simonpj/papers/haskell-retrospective/<br />
contains some brief comments on syntax and style,<br />
<br />
What now follows are descriptions of program documentation, file<br />
format, naming conventions and good programming practice (adapted form<br />
Matt's C/C++ Programming Guidelines and the Linux kernel coding<br />
style).<br />
<br />
<br />
=== Documentation ===<br />
<br />
<br />
Comments are to be written in application terms (i.e. user's point of<br />
view). Don't use technical terms - that's what the code is for!<br />
<br />
Comments should be written using correct spelling and grammar in complete<br />
sentences with punctation (in English only).<br />
<br />
"Generally, you want your comments to tell WHAT your code does, not HOW.<br />
Also, try to avoid putting comments inside a function body: if the<br />
function is so complex that you need to separately comment parts of it,<br />
you should probably" (... decompose it)<br />
<br />
Put a [http://haskell-haddock.readthedocs.io/en/latest/markup.html haddock comment] on top of every exported function and data type!<br />
Make sure haddock accepts these comments.<br />
<br />
=== File Format ===<br />
<br />
<br />
All Haskell source files start with a haddock header of the form:<br />
<br />
<haskell><br />
{- |<br />
Module : <File name or $Header$ to be replaced automatically><br />
Description : <optional short text displayed on contents page><br />
Copyright : (c) <Authors or Affiliations><br />
License : <license><br />
<br />
Maintainer : <email><br />
Stability : unstable | experimental | provisional | stable | frozen<br />
Portability : portable | non-portable (<reason>)<br />
<br />
<module description starting at first column><br />
-}<br />
</haskell><br />
<br />
A possible compiler pragma (like {-# LANGUAGE CPP #-}) may precede<br />
this header. The following hierarchical module name must of course<br />
match the file name.<br />
<br />
Make sure that the description is changed to meet the module (if the<br />
header was copied from elsewhere). Insert your email address as maintainer.<br />
<br />
Try to write portable (Haskell98) code. If you use e.g. multi-parameter<br />
type classes and functional dependencies the code becomes<br />
"non-portable (MPTC with FD)".<br />
<br />
The \$Header\$ entry will be automatically expanded.<br />
<br />
Lines should not be longer than 80 (preferably 75)<br />
characters to avoid wrapped lines (for casual readers)!<br />
<br />
Don't leave trailing white space in your code in every line.<br />
<br />
Expand all your tabs to spaces to avoid the danger of wrongly expanding<br />
them (or a different display of tabs versus eight spaces). Possibly put<br />
something like the following in your ~/.emacs file.<br />
<br />
(custom-set-variables '(indent-tabs-mode nil))<br />
<br />
The last character in your file should be a newline! Under solaris<br />
you'll get a warning if this is not the case and sometimes last lines<br />
without newlines are ignored (i.e. "#endif" without newline). Emacs<br />
usually asks for a final newline.<br />
<br />
You may use http://hackage.haskell.org/package/scan to check your file format.<br />
<br />
The whole module should not be too long (about 400 lines)<br />
<br />
Please have a look at the [http://haskell-haddock.readthedocs.io/en/latest/markup.html#the-module-description Haddock module header documentation].<br />
<br />
=== Naming Conventions ===<br />
<br />
<br />
In Haskell types start with capital and functions with lowercase<br />
letters, so only avoid infix identifiers! Defining symbolic infix<br />
identifiers should be left to library writers only.<br />
<br />
(The infix identifier "\\" at the end of a line causes cpp preprocessor<br />
problems.)<br />
<br />
Names (especially global ones) should be descriptive and if you need<br />
long names write them as mixed case words (aka camelCase). (but "tmp"<br />
is to be preferred over "thisVariableIsATemporaryCounter")<br />
<br />
Also in the standard libraries, function names with multiple words are<br />
written using the camelCase convention. Similarly, type, typeclass and<br />
constructor names are written using the StudlyCaps convention.<br />
<br />
Some parts of our code use underlines (without unnecessary uppercase<br />
letters) for long identifiers to better reflect names given with<br />
hyphens in the requirement documentation. Also such names should be<br />
transliterated to camlCase identifiers possibly adding a (consistent)<br />
suffix or prefix to avoid conflicts with keywords. However, instead of<br />
a recurring prefix or suffix you may consider to use qualified imports<br />
and names.<br />
<br />
<br />
=== Good Programming Practice ===<br />
<br />
<br />
"Functions should be short and sweet, and do just one thing. They should<br />
fit on one or two screenfuls of text (the ISO/ANSI screen size is 80x24,<br />
as we all know), and do one thing and do that well."<br />
<br />
Most haskell functions should be at most a few lines, only case<br />
expression over large data types (that should be avoided, too) may need<br />
corresponding space.<br />
<br />
The code should be succinct (though not obfuscated), readable and easy to<br />
maintain (after unforeseeable changes). Don't exploit exotic language<br />
features without good reason.<br />
<br />
It's not fixed how deep you indent (4 or 8 chars). You can break the<br />
line after "do", "let", "where", and "case .. of". Make sure that<br />
renamings don't destroy your layout. (If you get too far to the right,<br />
the code is unreadable anyway and needs to be decomposed.)<br />
<br />
Bad:<br />
<haskell><br />
case foo of Foo -> "Foo"<br />
Bar -> "Bar"<br />
</haskell><br />
<br />
Good:<br />
<haskell><br />
case <longer expression> of<br />
Foo -> "Foo"<br />
Bar -> "Bar"<br />
</haskell><br />
<br />
Avoid the notation with braces and semicolons since the layout rule<br />
forces you to properly align your alternatives.<br />
<br />
Respect compiler warnings. Supply type signatures, avoid shadowing and<br />
unused variables. Particularly avoid non-exhaustive and<br />
overlapping patterns. Missing unreachable cases can be filled in using<br />
"error" with a fixed string "<ModuleName>.<function>" to indicate the<br />
error position (in case the impossible should happen). Don't invest<br />
time to "show" the offending value, only do this temporarily when<br />
debugging the code.<br />
<br />
Don't leave unused or commented-out code in your files! Readers don't<br />
know what to think of it.<br />
<br />
<br />
==== Partial functions ====<br />
<br />
For partial functions do document their preconditions (if not obvious)<br />
and make sure that partial functions are only called when<br />
preconditions are obviously fulfilled (i.e. by a case statement or a<br />
previous test). Particularly the call of "head" should be used with<br />
care or (even better) be made obsolete by a case statement.<br />
<br />
Usually a case statement (and the import of isJust and fromJust from<br />
Data.[[Maybe]]) can be avoided by using the "maybe" function:<br />
<br />
<haskell><br />
maybe (error "<ModuleName>.<function>") id $ Map.lookup key map<br />
</haskell><br />
<br />
Generally we require you to be more explicit about failure<br />
cases. Surely a missing (or an irrefutable) pattern would precisely<br />
report the position of a runtime error, but these are not so obvious<br />
when reading the code.<br />
<br />
==== Let or where expressions ====<br />
<br />
Do avoid mixing and nesting "let" and "where". (I prefer the<br />
expression-stylistic "let".) Use auxiliary top-level functions that<br />
you do not export. Export lists also support the detection of unused<br />
functions.<br />
<br />
<br />
==== Code reuse ====<br />
<br />
If you notice that you're doing the same task again, try to generalize<br />
it in order to avoid duplicate code. It is frustrating to change the<br />
same error in several places.<br />
<br />
<br />
==== Application notation ====<br />
<br />
Many parentheses can be eliminated using the infix application operator <code>$</code><br />
with lowest priority. Try at least to avoid unnecessary parentheses in<br />
standard infix expression.<br />
<br />
<haskell><br />
f x : g x ++ h x<br />
<br />
a == 1 && b == 1 || a == 0 && b == 0<br />
</haskell><br />
<br />
Rather than putting a large final argument in parentheses (with a<br />
distant closing one) consider using <code>$</code> instead.<br />
<br />
<code>f (g x)</code> becomes <code>f $ g x</code> and consecutive applications<br />
<code>f (g (h x))</code> can be written as <code>f $ g $ h x</code> or <code>f . g $ h x</code>.<br />
<br />
A function definition like<br />
<code>f x = g $ h x</code> can be abbreviated to <code>f = g . h</code>.<br />
<br />
Note that the final argument may even be an infix- or case expression:<br />
<br />
<haskell><br />
map id $ c : l<br />
<br />
filter (const True) . map id $ case l of ...<br />
</haskell><br />
<br />
However, be aware that $-terms cannot be composed further in infix<br />
expressions.<br />
<br />
Probably wrong:<br />
<haskell><br />
f $ x ++ g $ x<br />
</haskell><br />
<br />
But the scope of an expression is also limited by the layout rule, so<br />
it is usually safe to use "$" on right hand sides.<br />
<br />
Ok:<br />
<br />
<haskell><br />
do f $ l<br />
++<br />
do g $ l<br />
</haskell><br />
<br />
Of course <code>$</code> can not be used in types. GHC has also some primitive<br />
functions involving the kind <code>#</code> that cannot be applied using <code>$</code>.<br />
<br />
Last warning: always leave spaces around <code>$</code> (and other mixfix<br />
operators) since a clash with template haskell is possible.<br />
<br />
(Also write <code>\ t</code> instead of <code>\t</code> in lambda expressions)<br />
<br />
==== List Comprehensions ====<br />
<br />
Use these only when "short and sweet". Prefer map, filter, and foldr!<br />
<br />
Instead of:<br />
<br />
<haskell><br />
[toUpper c | c <- s]<br />
</haskell><br />
<br />
write:<br />
<br />
<haskell><br />
map toUpper s<br />
</haskell><br />
<br />
Consider:<br />
<br />
<haskell><br />
[toUpper c | s <- strings, c <- s]<br />
</haskell><br />
<br />
Here it takes some time for the reader to find out which value depends<br />
on what other value and it is not so clear how many times the interim<br />
values s and c are used. In contrast to that the following can't be clearer:<br />
<br />
<haskell><br />
map toUpper (concat strings)<br />
</haskell><br />
<br />
<br />
When using higher order functions you can switch easier to data<br />
structures different from list. Compare:<br />
<br />
<haskell><br />
map (1+) list<br />
</haskell><br />
<br />
and:<br />
<br />
<haskell><br />
Set.map (1+) set<br />
</haskell><br />
<br />
<br />
==== Types ====<br />
<br />
Prefer proper data types over type synonyms or tuples even if you have<br />
to do more constructing and unpacking. This will make it easier to<br />
supply class instances later on. Don't put class constraints on<br />
a data type, constraints belong only to the functions that manipulate<br />
the data.<br />
<br />
Using type synonyms consistently is difficult over a longer time,<br />
because this is not checked by the compiler. (The types shown by<br />
the compiler may be unpredictable: i.e. FilePath, String or [Char])<br />
<br />
Take care if your data type has many variants (unless it is an<br />
enumeration type.) Don't repeat common parts in every variant since<br />
this will cause code duplication.<br />
<br />
Bad (to handle arguments in sync):<br />
<br />
<haskell><br />
data Mode f p = Box f p | Diamond f p<br />
</haskell><br />
<br />
Good (to handle arguments only once):<br />
<br />
<haskell><br />
data BoxOrDiamond = Box | Diamond<br />
<br />
data Mode f p = Mode BoxOrDiamond f p<br />
</haskell><br />
<br />
<br />
Consider (bad):<br />
<br />
<haskell><br />
data Tuple a b = Tuple a b | Undefined<br />
</haskell><br />
<br />
versus (better):<br />
<br />
<haskell><br />
data Tuple a b = Tuple a b<br />
</haskell><br />
<br />
and using:<br />
<br />
<haskell><br />
Maybe (Tuple a b)<br />
</haskell><br />
<br />
(or another monad) whenever an undefined result needs to be propagated<br />
<br />
<br />
==== Records ====<br />
<br />
For (large) records avoid the use of the constructor directly and<br />
remember that the order and number of fields may change.<br />
<br />
Take care with (the rare case of) depend polymorphic fields:<br />
<br />
<haskell><br />
data Fields a = VariantWithTwo<br />
{ field1 :: a<br />
, field2 :: a }<br />
</haskell><br />
<br />
The type of a value v can not be changed by only setting field1:<br />
<br />
<haskell><br />
v { field1 = f }<br />
</haskell><br />
<br />
Better construct a new value:<br />
<br />
<haskell><br />
VariantWithTwo { field1 = f } -- leaving field2 undefined<br />
</haskell><br />
<br />
Or use a polymorphic element that is instantiated by updating:<br />
<br />
<haskell><br />
empty = VariantWithTwo { field1 = [], field2 = [] }<br />
<br />
empty { field1 = [f] }<br />
</haskell><br />
<br />
Several variants with identical fields may avoid some code duplication<br />
when selecting and updating, though possibly not in a few<br />
depended polymorphic cases.<br />
<br />
However, I doubt if the following is a really good alternative to the<br />
above data Mode with data BoxOrDiamond.<br />
<br />
<haskell><br />
data Mode f p =<br />
Box { formula :: f, positions :: p }<br />
| Diamond { formula :: f, positions :: p }<br />
</haskell><br />
<br />
<br />
==== IO ====<br />
<br />
Try to strictly separate IO, Monad and pure (without do) function<br />
programming (possibly via separate modules).<br />
<br />
Bad:<br />
<br />
<haskell><br />
x <- return y<br />
...<br />
</haskell><br />
<br />
Good:<br />
<br />
<haskell><br />
let x = y<br />
...<br />
</haskell><br />
<br />
Don't use <code>Prelude.interact</code> and make sure your program does not depend<br />
on the (not always obvious) order of evaluation. E.g. don't read and<br />
write to the same file:<br />
<br />
This will fail:<br />
<br />
<haskell><br />
do s <- readFile f<br />
writeFile f $ 'a' : s<br />
</haskell><br />
<br />
because of lazy IO! (Writing is starting before reading is finished.)<br />
<br />
==== Trace ====<br />
<br />
Tracing is for debugging purposes only and should not be used as<br />
feedback for the user. Clean code is not cluttered by trace calls.<br />
<br />
<br />
==== Imports ====<br />
<br />
Standard library modules like Char. List, Maybe, Monad, etc should be<br />
imported by their hierarchical module name, i.e. the base package (so<br />
that haddock finds them):<br />
<br />
<haskell><br />
import Data.List<br />
import Control.Monad<br />
import System.Environment<br />
</haskell><br />
<br />
The libraries for Set and Map are to be imported qualified:<br />
<br />
<haskell><br />
import qualified Data.Set as Set<br />
import qualified Data.Map as Map<br />
</haskell><br />
<br />
<br />
==== Glasgow extensions and Classes ====<br />
<br />
[[Use of language extensions|Stay away from extensions]] as long as possible. Also use classes with<br />
care because soon the desire for overlapping instances (like for lists<br />
and strings) may arise. Then you may want MPTC (multi-parameter type<br />
classes), functional dependencies (FD), undecidable and possibly incoherent<br />
instances and then you are "in the wild" (according to SPJ).<br />
<br />
=== Style in other languages ===<br />
<br />
* [http://www.cs.caltech.edu/~cs20/a/style.html OCaml style]<br />
<br />
=== Final remarks ===<br />
<br />
Despite guidelines, writing "correct code" (without formal proof<br />
support yet) still remains the major challenge. As motivation to<br />
follow these guidelines consider the points that are from the "C++<br />
Coding Standard", where I replaced "C++" with "Haskell".<br />
<br />
Good Points:<br />
<br />
* programmers can go into any code and figure out what's going on<br />
<br />
* new people can get up to speed quickly<br />
<br />
* people new to Haskell are spared the need to develop a personal style and defend it to the death<br />
<br />
* people new to Haskell are spared making the same mistakes over and over again<br />
<br />
* people make fewer mistakes in consistent environments<br />
<br />
* programmers have a common enemy :-)<br />
<br />
Bad Points:<br />
<br />
* the standard is usually stupid because it was made by someone who doesn't understand Haskell<br />
<br />
* the standard is usually stupid because it's not what I do<br />
<br />
* standards reduce creativity<br />
<br />
* standards are unnecessary as long as people are consistent<br />
<br />
* standards enforce too much structure<br />
<br />
* people ignore standards anyway<br />
<br />
== Another guidelines ==<br />
<br />
[https://www.cse.unsw.edu.au/~cs3161/15s2/StyleGuide.html COMP3161]<br />
<br />
[http://docs.ganeti.org/ganeti/2.13/html/dev-codestyle.html#haskell Google's ganeti]<br />
<br />
[https://kowainik.github.io/posts/2019-02-06-style-guide kowainik]<br />
<br />
[https://github.com/Soostone/style-guides/blob/master/haskell-style-guide.md Soostone]<br />
<br />
[https://github.com/tibbe/haskell-style-guide/blob/master/haskell-style.md tibbe]<br />
<br />
[https://github.com/tweag/guides/blob/master/style/Haskell.md tweag]<br />
<br />
[[Category:Style]]</div>Wizzuphttps://wiki.haskell.org/index.php?title=Programming_guidelines&diff=62804Programming guidelines2019-03-01T07:51:31Z<p>Wizzup: /* Application notation */</p>
<hr />
<div>Programming guidelines shall help to make the code of a project better<br />
readable and maintainable by the varying number of contributors.<br />
<br />
It takes some programming experience to develop something like a<br />
personal "coding style" and guidelines only serve as rough shape for<br />
code. Guidelines should be followed by all members working on the<br />
project even if they prefer (or are already used to) different<br />
guidelines.<br />
<br />
These guidelines have been originally set up for the [http://hets.eu hets-project] and are<br />
now put on the [http://haskell.org/haskellwiki/ HaskellWiki] gradually<br />
integrating parts of the old hawiki<br />
entries [http://haskell.org/haskellwiki/Things_to_avoid ThingsToAvoid] and<br />
HaskellStyle (hopefully not<br />
hurting someone's copyrights). The other related entry<br />
TipsAndTricks treats more<br />
specific points that are left out here,<br />
<br />
Surely some style choices are a bit arbitrary (or "religious") and<br />
too restrictive with respect to language extensions. Nevertheless I hope<br />
to keep up these guidelines (at least as a basis) for our project<br />
in order to avoid maintaining diverging guidelines. Of course I want<br />
to supply - partly tool-dependent - reasons for certain decisions and<br />
also show alternatives by possibly bad examples. At the time of<br />
writing I use ghc-6.4.1, haddock-0.7 and (GNU-) emacs with the latest<br />
[http://www.haskell.org/haskell-mode/ haskell mode].<br />
<br />
The following quote and links are taken from<br />
HaskellStyle:<br />
<br />
We all have our own ideas about good Haskell style. There's More Than<br />
One Way To Do It. But some ways are better than others.<br />
<br />
Some comments from the GHC team about their internal coding<br />
standards can be found at<br />
http://hackage.haskell.org/trac/ghc/wiki/WorkingConventions<br />
<br />
Also http://research.microsoft.com/~simonpj/papers/haskell-retrospective/<br />
contains some brief comments on syntax and style,<br />
<br />
What now follows are descriptions of program documentation, file<br />
format, naming conventions and good programming practice (adapted form<br />
Matt's C/C++ Programming Guidelines and the Linux kernel coding<br />
style).<br />
<br />
<br />
=== Documentation ===<br />
<br />
<br />
Comments are to be written in application terms (i.e. user's point of<br />
view). Don't use technical terms - that's what the code is for!<br />
<br />
Comments should be written using correct spelling and grammar in complete<br />
sentences with punctation (in English only).<br />
<br />
"Generally, you want your comments to tell WHAT your code does, not HOW.<br />
Also, try to avoid putting comments inside a function body: if the<br />
function is so complex that you need to separately comment parts of it,<br />
you should probably" (... decompose it)<br />
<br />
Put a [http://haskell-haddock.readthedocs.io/en/latest/markup.html haddock comment] on top of every exported function and data type!<br />
Make sure haddock accepts these comments.<br />
<br />
=== File Format ===<br />
<br />
<br />
All Haskell source files start with a haddock header of the form:<br />
<br />
<haskell><br />
{- |<br />
Module : <File name or $Header$ to be replaced automatically><br />
Description : <optional short text displayed on contents page><br />
Copyright : (c) <Authors or Affiliations><br />
License : <license><br />
<br />
Maintainer : <email><br />
Stability : unstable | experimental | provisional | stable | frozen<br />
Portability : portable | non-portable (<reason>)<br />
<br />
<module description starting at first column><br />
-}<br />
</haskell><br />
<br />
A possible compiler pragma (like {-# LANGUAGE CPP #-}) may precede<br />
this header. The following hierarchical module name must of course<br />
match the file name.<br />
<br />
Make sure that the description is changed to meet the module (if the<br />
header was copied from elsewhere). Insert your email address as maintainer.<br />
<br />
Try to write portable (Haskell98) code. If you use e.g. multi-parameter<br />
type classes and functional dependencies the code becomes<br />
"non-portable (MPTC with FD)".<br />
<br />
The \$Header\$ entry will be automatically expanded.<br />
<br />
Lines should not be longer than 80 (preferably 75)<br />
characters to avoid wrapped lines (for casual readers)!<br />
<br />
Don't leave trailing white space in your code in every line.<br />
<br />
Expand all your tabs to spaces to avoid the danger of wrongly expanding<br />
them (or a different display of tabs versus eight spaces). Possibly put<br />
something like the following in your ~/.emacs file.<br />
<br />
(custom-set-variables '(indent-tabs-mode nil))<br />
<br />
The last character in your file should be a newline! Under solaris<br />
you'll get a warning if this is not the case and sometimes last lines<br />
without newlines are ignored (i.e. "#endif" without newline). Emacs<br />
usually asks for a final newline.<br />
<br />
You may use http://hackage.haskell.org/package/scan to check your file format.<br />
<br />
The whole module should not be too long (about 400 lines)<br />
<br />
Please have a look at the [http://haskell-haddock.readthedocs.io/en/latest/markup.html#the-module-description Haddock module header documentation].<br />
<br />
=== Naming Conventions ===<br />
<br />
<br />
In Haskell types start with capital and functions with lowercase<br />
letters, so only avoid infix identifiers! Defining symbolic infix<br />
identifiers should be left to library writers only.<br />
<br />
(The infix identifier "\\" at the end of a line causes cpp preprocessor<br />
problems.)<br />
<br />
Names (especially global ones) should be descriptive and if you need<br />
long names write them as mixed case words (aka camelCase). (but "tmp"<br />
is to be preferred over "thisVariableIsATemporaryCounter")<br />
<br />
Also in the standard libraries, function names with multiple words are<br />
written using the camelCase convention. Similarly, type, typeclass and<br />
constructor names are written using the StudlyCaps convention.<br />
<br />
Some parts of our code use underlines (without unnecessary uppercase<br />
letters) for long identifiers to better reflect names given with<br />
hyphens in the requirement documentation. Also such names should be<br />
transliterated to camlCase identifiers possibly adding a (consistent)<br />
suffix or prefix to avoid conflicts with keywords. However, instead of<br />
a recurring prefix or suffix you may consider to use qualified imports<br />
and names.<br />
<br />
<br />
=== Good Programming Practice ===<br />
<br />
<br />
"Functions should be short and sweet, and do just one thing. They should<br />
fit on one or two screenfuls of text (the ISO/ANSI screen size is 80x24,<br />
as we all know), and do one thing and do that well."<br />
<br />
Most haskell functions should be at most a few lines, only case<br />
expression over large data types (that should be avoided, too) may need<br />
corresponding space.<br />
<br />
The code should be succinct (though not obfuscated), readable and easy to<br />
maintain (after unforeseeable changes). Don't exploit exotic language<br />
features without good reason.<br />
<br />
It's not fixed how deep you indent (4 or 8 chars). You can break the<br />
line after "do", "let", "where", and "case .. of". Make sure that<br />
renamings don't destroy your layout. (If you get too far to the right,<br />
the code is unreadable anyway and needs to be decomposed.)<br />
<br />
Bad:<br />
<haskell><br />
case foo of Foo -> "Foo"<br />
Bar -> "Bar"<br />
</haskell><br />
<br />
Good:<br />
<haskell><br />
case <longer expression> of<br />
Foo -> "Foo"<br />
Bar -> "Bar"<br />
</haskell><br />
<br />
Avoid the notation with braces and semicolons since the layout rule<br />
forces you to properly align your alternatives.<br />
<br />
Respect compiler warnings. Supply type signatures, avoid shadowing and<br />
unused variables. Particularly avoid non-exhaustive and<br />
overlapping patterns. Missing unreachable cases can be filled in using<br />
"error" with a fixed string "<ModuleName>.<function>" to indicate the<br />
error position (in case the impossible should happen). Don't invest<br />
time to "show" the offending value, only do this temporarily when<br />
debugging the code.<br />
<br />
Don't leave unused or commented-out code in your files! Readers don't<br />
know what to think of it.<br />
<br />
<br />
==== Partial functions ====<br />
<br />
For partial functions do document their preconditions (if not obvious)<br />
and make sure that partial functions are only called when<br />
preconditions are obviously fulfilled (i.e. by a case statement or a<br />
previous test). Particularly the call of "head" should be used with<br />
care or (even better) be made obsolete by a case statement.<br />
<br />
Usually a case statement (and the import of isJust and fromJust from<br />
Data.[[Maybe]]) can be avoided by using the "maybe" function:<br />
<br />
<haskell><br />
maybe (error "<ModuleName>.<function>") id $ Map.lookup key map<br />
</haskell><br />
<br />
Generally we require you to be more explicit about failure<br />
cases. Surely a missing (or an irrefutable) pattern would precisely<br />
report the position of a runtime error, but these are not so obvious<br />
when reading the code.<br />
<br />
==== Let or where expressions ====<br />
<br />
Do avoid mixing and nesting "let" and "where". (I prefer the<br />
expression-stylistic "let".) Use auxiliary top-level functions that<br />
you do not export. Export lists also support the detection of unused<br />
functions.<br />
<br />
<br />
==== Code reuse ====<br />
<br />
If you notice that you're doing the same task again, try to generalize<br />
it in order to avoid duplicate code. It is frustrating to change the<br />
same error in several places.<br />
<br />
<br />
==== Application notation ====<br />
<br />
Many parentheses can be eliminated using the infix application operator <code>$</code><br />
with lowest priority. Try at least to avoid unnecessary parentheses in<br />
standard infix expression.<br />
<br />
<haskell><br />
f x : g x ++ h x<br />
<br />
a == 1 && b == 1 || a == 0 && b == 0<br />
</haskell><br />
<br />
Rather than putting a large final argument in parentheses (with a<br />
distant closing one) consider using <code>$</code> instead.<br />
<br />
<code>f (g x)</code> becomes <code>f $ g x</code> and consecutive applications<br />
<code>f (g (h x))</code> can be written as <code>f $ g $ h x</code> or <code>f . g $ h x</code>.<br />
<br />
A function definition like<br />
<code>f x = g $ h x</code> can be abbreviated to <code>f = g . h</code>.<br />
<br />
Note that the final argument may even be an infix- or case expression:<br />
<br />
<haskell><br />
map id $ c : l<br />
<br />
filter (const True) . map id $ case l of ...<br />
</haskell><br />
<br />
However, be aware that $-terms cannot be composed further in infix<br />
expressions.<br />
<br />
Probably wrong:<br />
<haskell><br />
f $ x ++ g $ x<br />
</haskell><br />
<br />
But the scope of an expression is also limited by the layout rule, so<br />
it is usually safe to use "$" on right hand sides.<br />
<br />
Ok:<br />
<br />
<haskell><br />
do f $ l<br />
++<br />
do g $ l<br />
</haskell><br />
<br />
Of course <code>$</code> can not be used in types. GHC has also some primitive<br />
functions involving the kind <code>#</code> that cannot be applied using <code>$</code>.<br />
<br />
Last warning: always leave spaces around <code>$</code> (and other mixfix<br />
operators) since a clash with template haskell is possible.<br />
<br />
(Also write <code>\ t</code> instead of <code>\t</code> in lambda expressions)<br />
<br />
==== List Comprehensions ====<br />
<br />
Use these only when "short and sweet". Prefer map, filter, and foldr!<br />
<br />
Instead of:<br />
<br />
<haskell><br />
[toUpper c | c <- s]<br />
</haskell><br />
<br />
write:<br />
<br />
<haskell><br />
map toUpper s<br />
</haskell><br />
<br />
Consider:<br />
<br />
<haskell><br />
[toUpper c | s <- strings, c <- s]<br />
</haskell><br />
<br />
Here it takes some time for the reader to find out which value depends<br />
on what other value and it is not so clear how many times the interim<br />
values s and c are used. In contrast to that the following can't be clearer:<br />
<br />
<haskell><br />
map toUpper (concat strings)<br />
</haskell><br />
<br />
<br />
When using higher order functions you can switch easier to data<br />
structures different from list. Compare:<br />
<br />
<haskell><br />
map (1+) list<br />
</haskell><br />
<br />
and:<br />
<br />
<haskell><br />
Set.map (1+) set<br />
</haskell><br />
<br />
<br />
==== Types ====<br />
<br />
Prefer proper data types over type synonyms or tuples even if you have<br />
to do more constructing and unpacking. This will make it easier to<br />
supply class instances later on. Don't put class constraints on<br />
a data type, constraints belong only to the functions that manipulate<br />
the data.<br />
<br />
Using type synonyms consistently is difficult over a longer time,<br />
because this is not checked by the compiler. (The types shown by<br />
the compiler may be unpredictable: i.e. FilePath, String or [Char])<br />
<br />
Take care if your data type has many variants (unless it is an<br />
enumeration type.) Don't repeat common parts in every variant since<br />
this will cause code duplication.<br />
<br />
Bad (to handle arguments in sync):<br />
<br />
<haskell><br />
data Mode f p = Box f p | Diamond f p<br />
</haskell><br />
<br />
Good (to handle arguments only once):<br />
<br />
<haskell><br />
data BoxOrDiamond = Box | Diamond<br />
<br />
data Mode f p = Mode BoxOrDiamond f p<br />
</haskell><br />
<br />
<br />
Consider (bad):<br />
<br />
<haskell><br />
data Tuple a b = Tuple a b | Undefined<br />
</haskell><br />
<br />
versus (better):<br />
<br />
<haskell><br />
data Tuple a b = Tuple a b<br />
</haskell><br />
<br />
and using:<br />
<br />
<haskell><br />
Maybe (Tuple a b)<br />
</haskell><br />
<br />
(or another monad) whenever an undefined result needs to be propagated<br />
<br />
<br />
==== Records ====<br />
<br />
For (large) records avoid the use of the constructor directly and<br />
remember that the order and number of fields may change.<br />
<br />
Take care with (the rare case of) depend polymorphic fields:<br />
<br />
<haskell><br />
data Fields a = VariantWithTwo<br />
{ field1 :: a<br />
, field2 :: a }<br />
</haskell><br />
<br />
The type of a value v can not be changed by only setting field1:<br />
<br />
<haskell><br />
v { field1 = f }<br />
</haskell><br />
<br />
Better construct a new value:<br />
<br />
<haskell><br />
VariantWithTwo { field1 = f } -- leaving field2 undefined<br />
</haskell><br />
<br />
Or use a polymorphic element that is instantiated by updating:<br />
<br />
<haskell><br />
empty = VariantWithTwo { field1 = [], field2 = [] }<br />
<br />
empty { field1 = [f] }<br />
</haskell><br />
<br />
Several variants with identical fields may avoid some code duplication<br />
when selecting and updating, though possibly not in a few<br />
depended polymorphic cases.<br />
<br />
However, I doubt if the following is a really good alternative to the<br />
above data Mode with data BoxOrDiamond.<br />
<br />
<haskell><br />
data Mode f p =<br />
Box { formula :: f, positions :: p }<br />
| Diamond { formula :: f, positions :: p }<br />
</haskell><br />
<br />
<br />
==== IO ====<br />
<br />
Try to strictly separate IO, Monad and pure (without do) function<br />
programming (possibly via separate modules).<br />
<br />
Bad:<br />
<br />
<haskell><br />
x <- return y<br />
...<br />
</haskell><br />
<br />
Good:<br />
<br />
<haskell><br />
let x = y<br />
...<br />
</haskell><br />
<br />
Don't use <code>Prelude.interact</code> and make sure your program does not depend<br />
on the (not always obvious) order of evaluation. E.g. don't read and<br />
write to the same file:<br />
<br />
This will fail:<br />
<br />
<haskell><br />
do s <- readFile f<br />
writeFile f $ 'a' : s<br />
</haskell><br />
<br />
because of lazy IO! (Writing is starting before reading is finished.)<br />
<br />
==== Trace ====<br />
<br />
Tracing is for debugging purposes only and should not be used as<br />
feedback for the user. Clean code is not cluttered by trace calls.<br />
<br />
<br />
==== Imports ====<br />
<br />
Standard library modules like Char. List, Maybe, Monad, etc should be<br />
imported by their hierarchical module name, i.e. the base package (so<br />
that haddock finds them):<br />
<br />
<haskell><br />
import Data.List<br />
import Control.Monad<br />
import System.Environment<br />
</haskell><br />
<br />
The libraries for Set and Map are to be imported qualified:<br />
<br />
<haskell><br />
import qualified Data.Set as Set<br />
import qualified Data.Map as Map<br />
</haskell><br />
<br />
<br />
==== Glasgow extensions and Classes ====<br />
<br />
[[Use of language extensions|Stay away from extensions]] as long as possible. Also use classes with<br />
care because soon the desire for overlapping instances (like for lists<br />
and strings) may arise. Then you may want MPTC (multi-parameter type<br />
classes), functional dependencies (FD), undecidable and possibly incoherent<br />
instances and then you are "in the wild" (according to SPJ).<br />
<br />
=== Style in other languages ===<br />
<br />
* [http://www.cs.caltech.edu/~cs20/a/style.html OCaml style]<br />
<br />
=== Final remarks ===<br />
<br />
Despite guidelines, writing "correct code" (without formal proof<br />
support yet) still remains the major challenge. As motivation to<br />
follow these guidelines consider the points that are from the "C++<br />
Coding Standard", where I replaced "C++" with "Haskell".<br />
<br />
Good Points:<br />
<br />
* programmers can go into any code and figure out what's going on<br />
<br />
* new people can get up to speed quickly<br />
<br />
* people new to Haskell are spared the need to develop a personal style and defend it to the death<br />
<br />
* people new to Haskell are spared making the same mistakes over and over again<br />
<br />
* people make fewer mistakes in consistent environments<br />
<br />
* programmers have a common enemy :-)<br />
<br />
Bad Points:<br />
<br />
* the standard is usually stupid because it was made by someone who doesn't understand Haskell<br />
<br />
* the standard is usually stupid because it's not what I do<br />
<br />
* standards reduce creativity<br />
<br />
* standards are unnecessary as long as people are consistent<br />
<br />
* standards enforce too much structure<br />
<br />
* people ignore standards anyway<br />
<br />
== Another guidelines ==<br />
<br />
[https://github.com/tibbe/haskell-style-guide/blob/master/haskell-style.md tibbe/haskell-style-guide]<br />
<br />
<br />
[[Category:Style]]</div>Wizzuphttps://wiki.haskell.org/index.php?title=Programming_guidelines&diff=62803Programming guidelines2019-03-01T07:47:20Z<p>Wizzup: /* IO */</p>
<hr />
<div>Programming guidelines shall help to make the code of a project better<br />
readable and maintainable by the varying number of contributors.<br />
<br />
It takes some programming experience to develop something like a<br />
personal "coding style" and guidelines only serve as rough shape for<br />
code. Guidelines should be followed by all members working on the<br />
project even if they prefer (or are already used to) different<br />
guidelines.<br />
<br />
These guidelines have been originally set up for the [http://hets.eu hets-project] and are<br />
now put on the [http://haskell.org/haskellwiki/ HaskellWiki] gradually<br />
integrating parts of the old hawiki<br />
entries [http://haskell.org/haskellwiki/Things_to_avoid ThingsToAvoid] and<br />
HaskellStyle (hopefully not<br />
hurting someone's copyrights). The other related entry<br />
TipsAndTricks treats more<br />
specific points that are left out here,<br />
<br />
Surely some style choices are a bit arbitrary (or "religious") and<br />
too restrictive with respect to language extensions. Nevertheless I hope<br />
to keep up these guidelines (at least as a basis) for our project<br />
in order to avoid maintaining diverging guidelines. Of course I want<br />
to supply - partly tool-dependent - reasons for certain decisions and<br />
also show alternatives by possibly bad examples. At the time of<br />
writing I use ghc-6.4.1, haddock-0.7 and (GNU-) emacs with the latest<br />
[http://www.haskell.org/haskell-mode/ haskell mode].<br />
<br />
The following quote and links are taken from<br />
HaskellStyle:<br />
<br />
We all have our own ideas about good Haskell style. There's More Than<br />
One Way To Do It. But some ways are better than others.<br />
<br />
Some comments from the GHC team about their internal coding<br />
standards can be found at<br />
http://hackage.haskell.org/trac/ghc/wiki/WorkingConventions<br />
<br />
Also http://research.microsoft.com/~simonpj/papers/haskell-retrospective/<br />
contains some brief comments on syntax and style,<br />
<br />
What now follows are descriptions of program documentation, file<br />
format, naming conventions and good programming practice (adapted form<br />
Matt's C/C++ Programming Guidelines and the Linux kernel coding<br />
style).<br />
<br />
<br />
=== Documentation ===<br />
<br />
<br />
Comments are to be written in application terms (i.e. user's point of<br />
view). Don't use technical terms - that's what the code is for!<br />
<br />
Comments should be written using correct spelling and grammar in complete<br />
sentences with punctation (in English only).<br />
<br />
"Generally, you want your comments to tell WHAT your code does, not HOW.<br />
Also, try to avoid putting comments inside a function body: if the<br />
function is so complex that you need to separately comment parts of it,<br />
you should probably" (... decompose it)<br />
<br />
Put a [http://haskell-haddock.readthedocs.io/en/latest/markup.html haddock comment] on top of every exported function and data type!<br />
Make sure haddock accepts these comments.<br />
<br />
=== File Format ===<br />
<br />
<br />
All Haskell source files start with a haddock header of the form:<br />
<br />
<haskell><br />
{- |<br />
Module : <File name or $Header$ to be replaced automatically><br />
Description : <optional short text displayed on contents page><br />
Copyright : (c) <Authors or Affiliations><br />
License : <license><br />
<br />
Maintainer : <email><br />
Stability : unstable | experimental | provisional | stable | frozen<br />
Portability : portable | non-portable (<reason>)<br />
<br />
<module description starting at first column><br />
-}<br />
</haskell><br />
<br />
A possible compiler pragma (like {-# LANGUAGE CPP #-}) may precede<br />
this header. The following hierarchical module name must of course<br />
match the file name.<br />
<br />
Make sure that the description is changed to meet the module (if the<br />
header was copied from elsewhere). Insert your email address as maintainer.<br />
<br />
Try to write portable (Haskell98) code. If you use e.g. multi-parameter<br />
type classes and functional dependencies the code becomes<br />
"non-portable (MPTC with FD)".<br />
<br />
The \$Header\$ entry will be automatically expanded.<br />
<br />
Lines should not be longer than 80 (preferably 75)<br />
characters to avoid wrapped lines (for casual readers)!<br />
<br />
Don't leave trailing white space in your code in every line.<br />
<br />
Expand all your tabs to spaces to avoid the danger of wrongly expanding<br />
them (or a different display of tabs versus eight spaces). Possibly put<br />
something like the following in your ~/.emacs file.<br />
<br />
(custom-set-variables '(indent-tabs-mode nil))<br />
<br />
The last character in your file should be a newline! Under solaris<br />
you'll get a warning if this is not the case and sometimes last lines<br />
without newlines are ignored (i.e. "#endif" without newline). Emacs<br />
usually asks for a final newline.<br />
<br />
You may use http://hackage.haskell.org/package/scan to check your file format.<br />
<br />
The whole module should not be too long (about 400 lines)<br />
<br />
Please have a look at the [http://haskell-haddock.readthedocs.io/en/latest/markup.html#the-module-description Haddock module header documentation].<br />
<br />
=== Naming Conventions ===<br />
<br />
<br />
In Haskell types start with capital and functions with lowercase<br />
letters, so only avoid infix identifiers! Defining symbolic infix<br />
identifiers should be left to library writers only.<br />
<br />
(The infix identifier "\\" at the end of a line causes cpp preprocessor<br />
problems.)<br />
<br />
Names (especially global ones) should be descriptive and if you need<br />
long names write them as mixed case words (aka camelCase). (but "tmp"<br />
is to be preferred over "thisVariableIsATemporaryCounter")<br />
<br />
Also in the standard libraries, function names with multiple words are<br />
written using the camelCase convention. Similarly, type, typeclass and<br />
constructor names are written using the StudlyCaps convention.<br />
<br />
Some parts of our code use underlines (without unnecessary uppercase<br />
letters) for long identifiers to better reflect names given with<br />
hyphens in the requirement documentation. Also such names should be<br />
transliterated to camlCase identifiers possibly adding a (consistent)<br />
suffix or prefix to avoid conflicts with keywords. However, instead of<br />
a recurring prefix or suffix you may consider to use qualified imports<br />
and names.<br />
<br />
<br />
=== Good Programming Practice ===<br />
<br />
<br />
"Functions should be short and sweet, and do just one thing. They should<br />
fit on one or two screenfuls of text (the ISO/ANSI screen size is 80x24,<br />
as we all know), and do one thing and do that well."<br />
<br />
Most haskell functions should be at most a few lines, only case<br />
expression over large data types (that should be avoided, too) may need<br />
corresponding space.<br />
<br />
The code should be succinct (though not obfuscated), readable and easy to<br />
maintain (after unforeseeable changes). Don't exploit exotic language<br />
features without good reason.<br />
<br />
It's not fixed how deep you indent (4 or 8 chars). You can break the<br />
line after "do", "let", "where", and "case .. of". Make sure that<br />
renamings don't destroy your layout. (If you get too far to the right,<br />
the code is unreadable anyway and needs to be decomposed.)<br />
<br />
Bad:<br />
<haskell><br />
case foo of Foo -> "Foo"<br />
Bar -> "Bar"<br />
</haskell><br />
<br />
Good:<br />
<haskell><br />
case <longer expression> of<br />
Foo -> "Foo"<br />
Bar -> "Bar"<br />
</haskell><br />
<br />
Avoid the notation with braces and semicolons since the layout rule<br />
forces you to properly align your alternatives.<br />
<br />
Respect compiler warnings. Supply type signatures, avoid shadowing and<br />
unused variables. Particularly avoid non-exhaustive and<br />
overlapping patterns. Missing unreachable cases can be filled in using<br />
"error" with a fixed string "<ModuleName>.<function>" to indicate the<br />
error position (in case the impossible should happen). Don't invest<br />
time to "show" the offending value, only do this temporarily when<br />
debugging the code.<br />
<br />
Don't leave unused or commented-out code in your files! Readers don't<br />
know what to think of it.<br />
<br />
<br />
==== Partial functions ====<br />
<br />
For partial functions do document their preconditions (if not obvious)<br />
and make sure that partial functions are only called when<br />
preconditions are obviously fulfilled (i.e. by a case statement or a<br />
previous test). Particularly the call of "head" should be used with<br />
care or (even better) be made obsolete by a case statement.<br />
<br />
Usually a case statement (and the import of isJust and fromJust from<br />
Data.[[Maybe]]) can be avoided by using the "maybe" function:<br />
<br />
<haskell><br />
maybe (error "<ModuleName>.<function>") id $ Map.lookup key map<br />
</haskell><br />
<br />
Generally we require you to be more explicit about failure<br />
cases. Surely a missing (or an irrefutable) pattern would precisely<br />
report the position of a runtime error, but these are not so obvious<br />
when reading the code.<br />
<br />
==== Let or where expressions ====<br />
<br />
Do avoid mixing and nesting "let" and "where". (I prefer the<br />
expression-stylistic "let".) Use auxiliary top-level functions that<br />
you do not export. Export lists also support the detection of unused<br />
functions.<br />
<br />
<br />
==== Code reuse ====<br />
<br />
If you notice that you're doing the same task again, try to generalize<br />
it in order to avoid duplicate code. It is frustrating to change the<br />
same error in several places.<br />
<br />
<br />
==== Application notation ====<br />
<br />
Many parentheses can be eliminated using the infix application operator "$"<br />
with lowest priority. Try at least to avoid unnecessary parentheses in<br />
standard infix expression.<br />
<br />
<haskell><br />
f x : g x ++ h x<br />
<br />
a == 1 && b == 1 || a == 0 && b == 0<br />
</haskell><br />
<br />
Rather than putting a large final argument in parentheses (with a<br />
distant closing one) consider using "$" instead.<br />
<br />
"f (g x)" becomes "f $ g x" and consecutive applications<br />
"f (g (h x))" can be written as "f $ g $ h x" or "f . g $ h x".<br />
<br />
A function definition like<br />
"f x = g $ h x" can be abbreviated to "f = g . h".<br />
<br />
Note that the final argument may even be an infix- or case expression:<br />
<br />
<haskell><br />
map id $ c : l<br />
<br />
filter (const True) . map id $ case l of ...<br />
</haskell><br />
<br />
However, be aware that $-terms cannot be composed further in infix<br />
expressions.<br />
<br />
Probably wrong:<br />
<haskell><br />
f $ x ++ g $ x<br />
</haskell><br />
<br />
But the scope of an expression is also limited by the layout rule, so<br />
it is usually safe to use "$" on right hand sides.<br />
<br />
Ok:<br />
<br />
<haskell><br />
do f $ l<br />
++<br />
do g $ l<br />
</haskell><br />
<br />
Of course "$" can not be used in types. GHC has also some primitive<br />
functions involving the kind "#" that cannot be applied using "$".<br />
<br />
Last warning: always leave spaces around "$" (and other mixfix<br />
operators) since a clash with template haskell is possible.<br />
<br />
(Also write "\ t" instead of "\t" in lambda expressions)<br />
<br />
<br />
==== List Comprehensions ====<br />
<br />
Use these only when "short and sweet". Prefer map, filter, and foldr!<br />
<br />
Instead of:<br />
<br />
<haskell><br />
[toUpper c | c <- s]<br />
</haskell><br />
<br />
write:<br />
<br />
<haskell><br />
map toUpper s<br />
</haskell><br />
<br />
Consider:<br />
<br />
<haskell><br />
[toUpper c | s <- strings, c <- s]<br />
</haskell><br />
<br />
Here it takes some time for the reader to find out which value depends<br />
on what other value and it is not so clear how many times the interim<br />
values s and c are used. In contrast to that the following can't be clearer:<br />
<br />
<haskell><br />
map toUpper (concat strings)<br />
</haskell><br />
<br />
<br />
When using higher order functions you can switch easier to data<br />
structures different from list. Compare:<br />
<br />
<haskell><br />
map (1+) list<br />
</haskell><br />
<br />
and:<br />
<br />
<haskell><br />
Set.map (1+) set<br />
</haskell><br />
<br />
<br />
==== Types ====<br />
<br />
Prefer proper data types over type synonyms or tuples even if you have<br />
to do more constructing and unpacking. This will make it easier to<br />
supply class instances later on. Don't put class constraints on<br />
a data type, constraints belong only to the functions that manipulate<br />
the data.<br />
<br />
Using type synonyms consistently is difficult over a longer time,<br />
because this is not checked by the compiler. (The types shown by<br />
the compiler may be unpredictable: i.e. FilePath, String or [Char])<br />
<br />
Take care if your data type has many variants (unless it is an<br />
enumeration type.) Don't repeat common parts in every variant since<br />
this will cause code duplication.<br />
<br />
Bad (to handle arguments in sync):<br />
<br />
<haskell><br />
data Mode f p = Box f p | Diamond f p<br />
</haskell><br />
<br />
Good (to handle arguments only once):<br />
<br />
<haskell><br />
data BoxOrDiamond = Box | Diamond<br />
<br />
data Mode f p = Mode BoxOrDiamond f p<br />
</haskell><br />
<br />
<br />
Consider (bad):<br />
<br />
<haskell><br />
data Tuple a b = Tuple a b | Undefined<br />
</haskell><br />
<br />
versus (better):<br />
<br />
<haskell><br />
data Tuple a b = Tuple a b<br />
</haskell><br />
<br />
and using:<br />
<br />
<haskell><br />
Maybe (Tuple a b)<br />
</haskell><br />
<br />
(or another monad) whenever an undefined result needs to be propagated<br />
<br />
<br />
==== Records ====<br />
<br />
For (large) records avoid the use of the constructor directly and<br />
remember that the order and number of fields may change.<br />
<br />
Take care with (the rare case of) depend polymorphic fields:<br />
<br />
<haskell><br />
data Fields a = VariantWithTwo<br />
{ field1 :: a<br />
, field2 :: a }<br />
</haskell><br />
<br />
The type of a value v can not be changed by only setting field1:<br />
<br />
<haskell><br />
v { field1 = f }<br />
</haskell><br />
<br />
Better construct a new value:<br />
<br />
<haskell><br />
VariantWithTwo { field1 = f } -- leaving field2 undefined<br />
</haskell><br />
<br />
Or use a polymorphic element that is instantiated by updating:<br />
<br />
<haskell><br />
empty = VariantWithTwo { field1 = [], field2 = [] }<br />
<br />
empty { field1 = [f] }<br />
</haskell><br />
<br />
Several variants with identical fields may avoid some code duplication<br />
when selecting and updating, though possibly not in a few<br />
depended polymorphic cases.<br />
<br />
However, I doubt if the following is a really good alternative to the<br />
above data Mode with data BoxOrDiamond.<br />
<br />
<haskell><br />
data Mode f p =<br />
Box { formula :: f, positions :: p }<br />
| Diamond { formula :: f, positions :: p }<br />
</haskell><br />
<br />
<br />
==== IO ====<br />
<br />
Try to strictly separate IO, Monad and pure (without do) function<br />
programming (possibly via separate modules).<br />
<br />
Bad:<br />
<br />
<haskell><br />
x <- return y<br />
...<br />
</haskell><br />
<br />
Good:<br />
<br />
<haskell><br />
let x = y<br />
...<br />
</haskell><br />
<br />
Don't use <code>Prelude.interact</code> and make sure your program does not depend<br />
on the (not always obvious) order of evaluation. E.g. don't read and<br />
write to the same file:<br />
<br />
This will fail:<br />
<br />
<haskell><br />
do s <- readFile f<br />
writeFile f $ 'a' : s<br />
</haskell><br />
<br />
because of lazy IO! (Writing is starting before reading is finished.)<br />
<br />
==== Trace ====<br />
<br />
Tracing is for debugging purposes only and should not be used as<br />
feedback for the user. Clean code is not cluttered by trace calls.<br />
<br />
<br />
==== Imports ====<br />
<br />
Standard library modules like Char. List, Maybe, Monad, etc should be<br />
imported by their hierarchical module name, i.e. the base package (so<br />
that haddock finds them):<br />
<br />
<haskell><br />
import Data.List<br />
import Control.Monad<br />
import System.Environment<br />
</haskell><br />
<br />
The libraries for Set and Map are to be imported qualified:<br />
<br />
<haskell><br />
import qualified Data.Set as Set<br />
import qualified Data.Map as Map<br />
</haskell><br />
<br />
<br />
==== Glasgow extensions and Classes ====<br />
<br />
[[Use of language extensions|Stay away from extensions]] as long as possible. Also use classes with<br />
care because soon the desire for overlapping instances (like for lists<br />
and strings) may arise. Then you may want MPTC (multi-parameter type<br />
classes), functional dependencies (FD), undecidable and possibly incoherent<br />
instances and then you are "in the wild" (according to SPJ).<br />
<br />
=== Style in other languages ===<br />
<br />
* [http://www.cs.caltech.edu/~cs20/a/style.html OCaml style]<br />
<br />
=== Final remarks ===<br />
<br />
Despite guidelines, writing "correct code" (without formal proof<br />
support yet) still remains the major challenge. As motivation to<br />
follow these guidelines consider the points that are from the "C++<br />
Coding Standard", where I replaced "C++" with "Haskell".<br />
<br />
Good Points:<br />
<br />
* programmers can go into any code and figure out what's going on<br />
<br />
* new people can get up to speed quickly<br />
<br />
* people new to Haskell are spared the need to develop a personal style and defend it to the death<br />
<br />
* people new to Haskell are spared making the same mistakes over and over again<br />
<br />
* people make fewer mistakes in consistent environments<br />
<br />
* programmers have a common enemy :-)<br />
<br />
Bad Points:<br />
<br />
* the standard is usually stupid because it was made by someone who doesn't understand Haskell<br />
<br />
* the standard is usually stupid because it's not what I do<br />
<br />
* standards reduce creativity<br />
<br />
* standards are unnecessary as long as people are consistent<br />
<br />
* standards enforce too much structure<br />
<br />
* people ignore standards anyway<br />
<br />
== Another guidelines ==<br />
<br />
[https://github.com/tibbe/haskell-style-guide/blob/master/haskell-style.md tibbe/haskell-style-guide]<br />
<br />
<br />
[[Category:Style]]</div>Wizzuphttps://wiki.haskell.org/index.php?title=Programming_guidelines&diff=62802Programming guidelines2019-03-01T07:22:23Z<p>Wizzup: format code</p>
<hr />
<div>Programming guidelines shall help to make the code of a project better<br />
readable and maintainable by the varying number of contributors.<br />
<br />
It takes some programming experience to develop something like a<br />
personal "coding style" and guidelines only serve as rough shape for<br />
code. Guidelines should be followed by all members working on the<br />
project even if they prefer (or are already used to) different<br />
guidelines.<br />
<br />
These guidelines have been originally set up for the [http://hets.eu hets-project] and are<br />
now put on the [http://haskell.org/haskellwiki/ HaskellWiki] gradually<br />
integrating parts of the old hawiki<br />
entries [http://haskell.org/haskellwiki/Things_to_avoid ThingsToAvoid] and<br />
HaskellStyle (hopefully not<br />
hurting someone's copyrights). The other related entry<br />
TipsAndTricks treats more<br />
specific points that are left out here,<br />
<br />
Surely some style choices are a bit arbitrary (or "religious") and<br />
too restrictive with respect to language extensions. Nevertheless I hope<br />
to keep up these guidelines (at least as a basis) for our project<br />
in order to avoid maintaining diverging guidelines. Of course I want<br />
to supply - partly tool-dependent - reasons for certain decisions and<br />
also show alternatives by possibly bad examples. At the time of<br />
writing I use ghc-6.4.1, haddock-0.7 and (GNU-) emacs with the latest<br />
[http://www.haskell.org/haskell-mode/ haskell mode].<br />
<br />
The following quote and links are taken from<br />
HaskellStyle:<br />
<br />
We all have our own ideas about good Haskell style. There's More Than<br />
One Way To Do It. But some ways are better than others.<br />
<br />
Some comments from the GHC team about their internal coding<br />
standards can be found at<br />
http://hackage.haskell.org/trac/ghc/wiki/WorkingConventions<br />
<br />
Also http://research.microsoft.com/~simonpj/papers/haskell-retrospective/<br />
contains some brief comments on syntax and style,<br />
<br />
What now follows are descriptions of program documentation, file<br />
format, naming conventions and good programming practice (adapted form<br />
Matt's C/C++ Programming Guidelines and the Linux kernel coding<br />
style).<br />
<br />
<br />
=== Documentation ===<br />
<br />
<br />
Comments are to be written in application terms (i.e. user's point of<br />
view). Don't use technical terms - that's what the code is for!<br />
<br />
Comments should be written using correct spelling and grammar in complete<br />
sentences with punctation (in English only).<br />
<br />
"Generally, you want your comments to tell WHAT your code does, not HOW.<br />
Also, try to avoid putting comments inside a function body: if the<br />
function is so complex that you need to separately comment parts of it,<br />
you should probably" (... decompose it)<br />
<br />
Put a [http://haskell-haddock.readthedocs.io/en/latest/markup.html haddock comment] on top of every exported function and data type!<br />
Make sure haddock accepts these comments.<br />
<br />
=== File Format ===<br />
<br />
<br />
All Haskell source files start with a haddock header of the form:<br />
<br />
<haskell><br />
{- |<br />
Module : <File name or $Header$ to be replaced automatically><br />
Description : <optional short text displayed on contents page><br />
Copyright : (c) <Authors or Affiliations><br />
License : <license><br />
<br />
Maintainer : <email><br />
Stability : unstable | experimental | provisional | stable | frozen<br />
Portability : portable | non-portable (<reason>)<br />
<br />
<module description starting at first column><br />
-}<br />
</haskell><br />
<br />
A possible compiler pragma (like {-# LANGUAGE CPP #-}) may precede<br />
this header. The following hierarchical module name must of course<br />
match the file name.<br />
<br />
Make sure that the description is changed to meet the module (if the<br />
header was copied from elsewhere). Insert your email address as maintainer.<br />
<br />
Try to write portable (Haskell98) code. If you use e.g. multi-parameter<br />
type classes and functional dependencies the code becomes<br />
"non-portable (MPTC with FD)".<br />
<br />
The \$Header\$ entry will be automatically expanded.<br />
<br />
Lines should not be longer than 80 (preferably 75)<br />
characters to avoid wrapped lines (for casual readers)!<br />
<br />
Don't leave trailing white space in your code in every line.<br />
<br />
Expand all your tabs to spaces to avoid the danger of wrongly expanding<br />
them (or a different display of tabs versus eight spaces). Possibly put<br />
something like the following in your ~/.emacs file.<br />
<br />
(custom-set-variables '(indent-tabs-mode nil))<br />
<br />
The last character in your file should be a newline! Under solaris<br />
you'll get a warning if this is not the case and sometimes last lines<br />
without newlines are ignored (i.e. "#endif" without newline). Emacs<br />
usually asks for a final newline.<br />
<br />
You may use http://hackage.haskell.org/package/scan to check your file format.<br />
<br />
The whole module should not be too long (about 400 lines)<br />
<br />
Please have a look at the [http://haskell-haddock.readthedocs.io/en/latest/markup.html#the-module-description Haddock module header documentation].<br />
<br />
=== Naming Conventions ===<br />
<br />
<br />
In Haskell types start with capital and functions with lowercase<br />
letters, so only avoid infix identifiers! Defining symbolic infix<br />
identifiers should be left to library writers only.<br />
<br />
(The infix identifier "\\" at the end of a line causes cpp preprocessor<br />
problems.)<br />
<br />
Names (especially global ones) should be descriptive and if you need<br />
long names write them as mixed case words (aka camelCase). (but "tmp"<br />
is to be preferred over "thisVariableIsATemporaryCounter")<br />
<br />
Also in the standard libraries, function names with multiple words are<br />
written using the camelCase convention. Similarly, type, typeclass and<br />
constructor names are written using the StudlyCaps convention.<br />
<br />
Some parts of our code use underlines (without unnecessary uppercase<br />
letters) for long identifiers to better reflect names given with<br />
hyphens in the requirement documentation. Also such names should be<br />
transliterated to camlCase identifiers possibly adding a (consistent)<br />
suffix or prefix to avoid conflicts with keywords. However, instead of<br />
a recurring prefix or suffix you may consider to use qualified imports<br />
and names.<br />
<br />
<br />
=== Good Programming Practice ===<br />
<br />
<br />
"Functions should be short and sweet, and do just one thing. They should<br />
fit on one or two screenfuls of text (the ISO/ANSI screen size is 80x24,<br />
as we all know), and do one thing and do that well."<br />
<br />
Most haskell functions should be at most a few lines, only case<br />
expression over large data types (that should be avoided, too) may need<br />
corresponding space.<br />
<br />
The code should be succinct (though not obfuscated), readable and easy to<br />
maintain (after unforeseeable changes). Don't exploit exotic language<br />
features without good reason.<br />
<br />
It's not fixed how deep you indent (4 or 8 chars). You can break the<br />
line after "do", "let", "where", and "case .. of". Make sure that<br />
renamings don't destroy your layout. (If you get too far to the right,<br />
the code is unreadable anyway and needs to be decomposed.)<br />
<br />
Bad:<br />
<haskell><br />
case foo of Foo -> "Foo"<br />
Bar -> "Bar"<br />
</haskell><br />
<br />
Good:<br />
<haskell><br />
case <longer expression> of<br />
Foo -> "Foo"<br />
Bar -> "Bar"<br />
</haskell><br />
<br />
Avoid the notation with braces and semicolons since the layout rule<br />
forces you to properly align your alternatives.<br />
<br />
Respect compiler warnings. Supply type signatures, avoid shadowing and<br />
unused variables. Particularly avoid non-exhaustive and<br />
overlapping patterns. Missing unreachable cases can be filled in using<br />
"error" with a fixed string "<ModuleName>.<function>" to indicate the<br />
error position (in case the impossible should happen). Don't invest<br />
time to "show" the offending value, only do this temporarily when<br />
debugging the code.<br />
<br />
Don't leave unused or commented-out code in your files! Readers don't<br />
know what to think of it.<br />
<br />
<br />
==== Partial functions ====<br />
<br />
For partial functions do document their preconditions (if not obvious)<br />
and make sure that partial functions are only called when<br />
preconditions are obviously fulfilled (i.e. by a case statement or a<br />
previous test). Particularly the call of "head" should be used with<br />
care or (even better) be made obsolete by a case statement.<br />
<br />
Usually a case statement (and the import of isJust and fromJust from<br />
Data.[[Maybe]]) can be avoided by using the "maybe" function:<br />
<br />
<haskell><br />
maybe (error "<ModuleName>.<function>") id $ Map.lookup key map<br />
</haskell><br />
<br />
Generally we require you to be more explicit about failure<br />
cases. Surely a missing (or an irrefutable) pattern would precisely<br />
report the position of a runtime error, but these are not so obvious<br />
when reading the code.<br />
<br />
==== Let or where expressions ====<br />
<br />
Do avoid mixing and nesting "let" and "where". (I prefer the<br />
expression-stylistic "let".) Use auxiliary top-level functions that<br />
you do not export. Export lists also support the detection of unused<br />
functions.<br />
<br />
<br />
==== Code reuse ====<br />
<br />
If you notice that you're doing the same task again, try to generalize<br />
it in order to avoid duplicate code. It is frustrating to change the<br />
same error in several places.<br />
<br />
<br />
==== Application notation ====<br />
<br />
Many parentheses can be eliminated using the infix application operator "$"<br />
with lowest priority. Try at least to avoid unnecessary parentheses in<br />
standard infix expression.<br />
<br />
<haskell><br />
f x : g x ++ h x<br />
<br />
a == 1 && b == 1 || a == 0 && b == 0<br />
</haskell><br />
<br />
Rather than putting a large final argument in parentheses (with a<br />
distant closing one) consider using "$" instead.<br />
<br />
"f (g x)" becomes "f $ g x" and consecutive applications<br />
"f (g (h x))" can be written as "f $ g $ h x" or "f . g $ h x".<br />
<br />
A function definition like<br />
"f x = g $ h x" can be abbreviated to "f = g . h".<br />
<br />
Note that the final argument may even be an infix- or case expression:<br />
<br />
<haskell><br />
map id $ c : l<br />
<br />
filter (const True) . map id $ case l of ...<br />
</haskell><br />
<br />
However, be aware that $-terms cannot be composed further in infix<br />
expressions.<br />
<br />
Probably wrong:<br />
<haskell><br />
f $ x ++ g $ x<br />
</haskell><br />
<br />
But the scope of an expression is also limited by the layout rule, so<br />
it is usually safe to use "$" on right hand sides.<br />
<br />
Ok:<br />
<br />
<haskell><br />
do f $ l<br />
++<br />
do g $ l<br />
</haskell><br />
<br />
Of course "$" can not be used in types. GHC has also some primitive<br />
functions involving the kind "#" that cannot be applied using "$".<br />
<br />
Last warning: always leave spaces around "$" (and other mixfix<br />
operators) since a clash with template haskell is possible.<br />
<br />
(Also write "\ t" instead of "\t" in lambda expressions)<br />
<br />
<br />
==== List Comprehensions ====<br />
<br />
Use these only when "short and sweet". Prefer map, filter, and foldr!<br />
<br />
Instead of:<br />
<br />
<haskell><br />
[toUpper c | c <- s]<br />
</haskell><br />
<br />
write:<br />
<br />
<haskell><br />
map toUpper s<br />
</haskell><br />
<br />
Consider:<br />
<br />
<haskell><br />
[toUpper c | s <- strings, c <- s]<br />
</haskell><br />
<br />
Here it takes some time for the reader to find out which value depends<br />
on what other value and it is not so clear how many times the interim<br />
values s and c are used. In contrast to that the following can't be clearer:<br />
<br />
<haskell><br />
map toUpper (concat strings)<br />
</haskell><br />
<br />
<br />
When using higher order functions you can switch easier to data<br />
structures different from list. Compare:<br />
<br />
<haskell><br />
map (1+) list<br />
</haskell><br />
<br />
and:<br />
<br />
<haskell><br />
Set.map (1+) set<br />
</haskell><br />
<br />
<br />
==== Types ====<br />
<br />
Prefer proper data types over type synonyms or tuples even if you have<br />
to do more constructing and unpacking. This will make it easier to<br />
supply class instances later on. Don't put class constraints on<br />
a data type, constraints belong only to the functions that manipulate<br />
the data.<br />
<br />
Using type synonyms consistently is difficult over a longer time,<br />
because this is not checked by the compiler. (The types shown by<br />
the compiler may be unpredictable: i.e. FilePath, String or [Char])<br />
<br />
Take care if your data type has many variants (unless it is an<br />
enumeration type.) Don't repeat common parts in every variant since<br />
this will cause code duplication.<br />
<br />
Bad (to handle arguments in sync):<br />
<br />
<haskell><br />
data Mode f p = Box f p | Diamond f p<br />
</haskell><br />
<br />
Good (to handle arguments only once):<br />
<br />
<haskell><br />
data BoxOrDiamond = Box | Diamond<br />
<br />
data Mode f p = Mode BoxOrDiamond f p<br />
</haskell><br />
<br />
<br />
Consider (bad):<br />
<br />
<haskell><br />
data Tuple a b = Tuple a b | Undefined<br />
</haskell><br />
<br />
versus (better):<br />
<br />
<haskell><br />
data Tuple a b = Tuple a b<br />
</haskell><br />
<br />
and using:<br />
<br />
<haskell><br />
Maybe (Tuple a b)<br />
</haskell><br />
<br />
(or another monad) whenever an undefined result needs to be propagated<br />
<br />
<br />
==== Records ====<br />
<br />
For (large) records avoid the use of the constructor directly and<br />
remember that the order and number of fields may change.<br />
<br />
Take care with (the rare case of) depend polymorphic fields:<br />
<br />
<haskell><br />
data Fields a = VariantWithTwo<br />
{ field1 :: a<br />
, field2 :: a }<br />
</haskell><br />
<br />
The type of a value v can not be changed by only setting field1:<br />
<br />
<haskell><br />
v { field1 = f }<br />
</haskell><br />
<br />
Better construct a new value:<br />
<br />
<haskell><br />
VariantWithTwo { field1 = f } -- leaving field2 undefined<br />
</haskell><br />
<br />
Or use a polymorphic element that is instantiated by updating:<br />
<br />
<haskell><br />
empty = VariantWithTwo { field1 = [], field2 = [] }<br />
<br />
empty { field1 = [f] }<br />
</haskell><br />
<br />
Several variants with identical fields may avoid some code duplication<br />
when selecting and updating, though possibly not in a few<br />
depended polymorphic cases.<br />
<br />
However, I doubt if the following is a really good alternative to the<br />
above data Mode with data BoxOrDiamond.<br />
<br />
<haskell><br />
data Mode f p =<br />
Box { formula :: f, positions :: p }<br />
| Diamond { formula :: f, positions :: p }<br />
</haskell><br />
<br />
<br />
==== IO ====<br />
<br />
Try to strictly separate IO, Monad and pure (without do) function<br />
programming (possibly via separate modules).<br />
<br />
Bad:<br />
<br />
<haskell><br />
x <- return y<br />
...<br />
</haskell><br />
<br />
Good:<br />
<br />
<haskell><br />
let x = y<br />
...<br />
</haskell><br />
<br />
Don't use `Prelude.interact` and make sure your program does not depend<br />
on the (not always obvious) order of evaluation. E.g. don't read and<br />
write to the same file:<br />
<br />
This will fail:<br />
<br />
<haskell><br />
do s <- readFile f<br />
writeFile f $ 'a' : s<br />
</haskell><br />
<br />
because of lazy IO! (Writing is starting before reading is finished.)<br />
<br />
==== Trace ====<br />
<br />
Tracing is for debugging purposes only and should not be used as<br />
feedback for the user. Clean code is not cluttered by trace calls.<br />
<br />
<br />
==== Imports ====<br />
<br />
Standard library modules like Char. List, Maybe, Monad, etc should be<br />
imported by their hierarchical module name, i.e. the base package (so<br />
that haddock finds them):<br />
<br />
<haskell><br />
import Data.List<br />
import Control.Monad<br />
import System.Environment<br />
</haskell><br />
<br />
The libraries for Set and Map are to be imported qualified:<br />
<br />
<haskell><br />
import qualified Data.Set as Set<br />
import qualified Data.Map as Map<br />
</haskell><br />
<br />
<br />
==== Glasgow extensions and Classes ====<br />
<br />
[[Use of language extensions|Stay away from extensions]] as long as possible. Also use classes with<br />
care because soon the desire for overlapping instances (like for lists<br />
and strings) may arise. Then you may want MPTC (multi-parameter type<br />
classes), functional dependencies (FD), undecidable and possibly incoherent<br />
instances and then you are "in the wild" (according to SPJ).<br />
<br />
=== Style in other languages ===<br />
<br />
* [http://www.cs.caltech.edu/~cs20/a/style.html OCaml style]<br />
<br />
=== Final remarks ===<br />
<br />
Despite guidelines, writing "correct code" (without formal proof<br />
support yet) still remains the major challenge. As motivation to<br />
follow these guidelines consider the points that are from the "C++<br />
Coding Standard", where I replaced "C++" with "Haskell".<br />
<br />
Good Points:<br />
<br />
* programmers can go into any code and figure out what's going on<br />
<br />
* new people can get up to speed quickly<br />
<br />
* people new to Haskell are spared the need to develop a personal style and defend it to the death<br />
<br />
* people new to Haskell are spared making the same mistakes over and over again<br />
<br />
* people make fewer mistakes in consistent environments<br />
<br />
* programmers have a common enemy :-)<br />
<br />
Bad Points:<br />
<br />
* the standard is usually stupid because it was made by someone who doesn't understand Haskell<br />
<br />
* the standard is usually stupid because it's not what I do<br />
<br />
* standards reduce creativity<br />
<br />
* standards are unnecessary as long as people are consistent<br />
<br />
* standards enforce too much structure<br />
<br />
* people ignore standards anyway<br />
<br />
== Another guidelines ==<br />
<br />
[https://github.com/tibbe/haskell-style-guide/blob/master/haskell-style.md tibbe/haskell-style-guide]<br />
<br />
<br />
[[Category:Style]]</div>Wizzuphttps://wiki.haskell.org/index.php?title=Programming_guidelines&diff=62801Programming guidelines2019-03-01T07:06:10Z<p>Wizzup: update link to where the old link redirected to</p>
<hr />
<div>Programming guidelines shall help to make the code of a project better<br />
readable and maintainable by the varying number of contributors.<br />
<br />
It takes some programming experience to develop something like a<br />
personal "coding style" and guidelines only serve as rough shape for<br />
code. Guidelines should be followed by all members working on the<br />
project even if they prefer (or are already used to) different<br />
guidelines.<br />
<br />
These guidelines have been originally set up for the [http://hets.eu hets-project] and are<br />
now put on the [http://haskell.org/haskellwiki/ HaskellWiki] gradually<br />
integrating parts of the old hawiki<br />
entries [http://haskell.org/haskellwiki/Things_to_avoid ThingsToAvoid] and<br />
HaskellStyle (hopefully not<br />
hurting someone's copyrights). The other related entry<br />
TipsAndTricks treats more<br />
specific points that are left out here,<br />
<br />
Surely some style choices are a bit arbitrary (or "religious") and<br />
too restrictive with respect to language extensions. Nevertheless I hope<br />
to keep up these guidelines (at least as a basis) for our project<br />
in order to avoid maintaining diverging guidelines. Of course I want<br />
to supply - partly tool-dependent - reasons for certain decisions and<br />
also show alternatives by possibly bad examples. At the time of<br />
writing I use ghc-6.4.1, haddock-0.7 and (GNU-) emacs with the latest<br />
[http://www.haskell.org/haskell-mode/ haskell mode].<br />
<br />
The following quote and links are taken from<br />
HaskellStyle:<br />
<br />
We all have our own ideas about good Haskell style. There's More Than<br />
One Way To Do It. But some ways are better than others.<br />
<br />
Some comments from the GHC team about their internal coding<br />
standards can be found at<br />
http://hackage.haskell.org/trac/ghc/wiki/WorkingConventions<br />
<br />
Also http://research.microsoft.com/~simonpj/papers/haskell-retrospective/<br />
contains some brief comments on syntax and style,<br />
<br />
What now follows are descriptions of program documentation, file<br />
format, naming conventions and good programming practice (adapted form<br />
Matt's C/C++ Programming Guidelines and the Linux kernel coding<br />
style).<br />
<br />
<br />
=== Documentation ===<br />
<br />
<br />
Comments are to be written in application terms (i.e. user's point of<br />
view). Don't use technical terms - that's what the code is for!<br />
<br />
Comments should be written using correct spelling and grammar in complete<br />
sentences with punctation (in English only).<br />
<br />
"Generally, you want your comments to tell WHAT your code does, not HOW.<br />
Also, try to avoid putting comments inside a function body: if the<br />
function is so complex that you need to separately comment parts of it,<br />
you should probably" (... decompose it)<br />
<br />
Put a [http://haskell-haddock.readthedocs.io/en/latest/markup.html haddock comment] on top of every exported function and data type!<br />
Make sure haddock accepts these comments.<br />
<br />
=== File Format ===<br />
<br />
<br />
All Haskell source files start with a haddock header of the form:<br />
<br />
<pre><br />
{- |<br />
Module : <File name or $Header$ to be replaced automatically><br />
Description : <optional short text displayed on contents page><br />
Copyright : (c) <Authors or Affiliations><br />
License : <license><br />
<br />
Maintainer : <email><br />
Stability : unstable | experimental | provisional | stable | frozen<br />
Portability : portable | non-portable (<reason>)<br />
<br />
<module description starting at first column><br />
-}<br />
</pre><br />
<br />
A possible compiler pragma (like {-# LANGUAGE CPP #-}) may precede<br />
this header. The following hierarchical module name must of course<br />
match the file name.<br />
<br />
Make sure that the description is changed to meet the module (if the<br />
header was copied from elsewhere). Insert your email address as maintainer.<br />
<br />
Try to write portable (Haskell98) code. If you use e.g. multi-parameter<br />
type classes and functional dependencies the code becomes<br />
"non-portable (MPTC with FD)".<br />
<br />
The \$Header\$ entry will be automatically expanded.<br />
<br />
Lines should not be longer than 80 (preferably 75)<br />
characters to avoid wrapped lines (for casual readers)!<br />
<br />
Don't leave trailing white space in your code in every line.<br />
<br />
Expand all your tabs to spaces to avoid the danger of wrongly expanding<br />
them (or a different display of tabs versus eight spaces). Possibly put<br />
something like the following in your ~/.emacs file.<br />
<br />
(custom-set-variables '(indent-tabs-mode nil))<br />
<br />
The last character in your file should be a newline! Under solaris<br />
you'll get a warning if this is not the case and sometimes last lines<br />
without newlines are ignored (i.e. "#endif" without newline). Emacs<br />
usually asks for a final newline.<br />
<br />
You may use http://hackage.haskell.org/package/scan to check your file format.<br />
<br />
The whole module should not be too long (about 400 lines)<br />
<br />
Please have a look at the [http://haskell-haddock.readthedocs.io/en/latest/markup.html#the-module-description Haddock module header documentation].<br />
<br />
=== Naming Conventions ===<br />
<br />
<br />
In Haskell types start with capital and functions with lowercase<br />
letters, so only avoid infix identifiers! Defining symbolic infix<br />
identifiers should be left to library writers only.<br />
<br />
(The infix identifier "\\" at the end of a line causes cpp preprocessor<br />
problems.)<br />
<br />
Names (especially global ones) should be descriptive and if you need<br />
long names write them as mixed case words (aka camelCase). (but "tmp"<br />
is to be preferred over "thisVariableIsATemporaryCounter")<br />
<br />
Also in the standard libraries, function names with multiple words are<br />
written using the camelCase convention. Similarly, type, typeclass and<br />
constructor names are written using the StudlyCaps convention.<br />
<br />
Some parts of our code use underlines (without unnecessary uppercase<br />
letters) for long identifiers to better reflect names given with<br />
hyphens in the requirement documentation. Also such names should be<br />
transliterated to camlCase identifiers possibly adding a (consistent)<br />
suffix or prefix to avoid conflicts with keywords. However, instead of<br />
a recurring prefix or suffix you may consider to use qualified imports<br />
and names.<br />
<br />
<br />
=== Good Programming Practice ===<br />
<br />
<br />
"Functions should be short and sweet, and do just one thing. They should<br />
fit on one or two screenfuls of text (the ISO/ANSI screen size is 80x24,<br />
as we all know), and do one thing and do that well."<br />
<br />
Most haskell functions should be at most a few lines, only case<br />
expression over large data types (that should be avoided, too) may need<br />
corresponding space.<br />
<br />
The code should be succinct (though not obfuscated), readable and easy to<br />
maintain (after unforeseeable changes). Don't exploit exotic language<br />
features without good reason.<br />
<br />
It's not fixed how deep you indent (4 or 8 chars). You can break the<br />
line after "do", "let", "where", and "case .. of". Make sure that<br />
renamings don't destroy your layout. (If you get too far to the right,<br />
the code is unreadable anyway and needs to be decomposed.)<br />
<br />
Bad:<br />
case foo of Foo -> "Foo"<br />
Bar -> "Bar"<br />
Good:<br />
case <longer expression> of<br />
Foo -> "Foo"<br />
Bar -> "Bar"<br />
<br />
Avoid the notation with braces and semicolons since the layout rule<br />
forces you to properly align your alternatives.<br />
<br />
Respect compiler warnings. Supply type signatures, avoid shadowing and<br />
unused variables. Particularly avoid non-exhaustive and<br />
overlapping patterns. Missing unreachable cases can be filled in using<br />
"error" with a fixed string "<ModuleName>.<function>" to indicate the<br />
error position (in case the impossible should happen). Don't invest<br />
time to "show" the offending value, only do this temporarily when<br />
debugging the code.<br />
<br />
Don't leave unused or commented-out code in your files! Readers don't<br />
know what to think of it.<br />
<br />
<br />
<br />
==== Partial functions ====<br />
<br />
For partial functions do document their preconditions (if not obvious)<br />
and make sure that partial functions are only called when<br />
preconditions are obviously fulfilled (i.e. by a case statement or a<br />
previous test). Particularly the call of "head" should be used with<br />
care or (even better) be made obsolete by a case statement.<br />
<br />
Usually a case statement (and the import of isJust and fromJust from<br />
Data.[[Maybe]]) can be avoided by using the "maybe" function:<br />
<br />
maybe (error "<ModuleName>.<function>") id $ Map.lookup key map<br />
<br />
Generally we require you to be more explicit about failure<br />
cases. Surely a missing (or an irrefutable) pattern would precisely<br />
report the position of a runtime error, but these are not so obvious<br />
when reading the code.<br />
<br />
==== Let or where expressions ====<br />
<br />
Do avoid mixing and nesting "let" and "where". (I prefer the<br />
expression-stylistic "let".) Use auxiliary top-level functions that<br />
you do not export. Export lists also support the detection of unused<br />
functions.<br />
<br />
<br />
==== Code reuse ====<br />
<br />
If you notice that you're doing the same task again, try to generalize<br />
it in order to avoid duplicate code. It is frustrating to change the<br />
same error in several places.<br />
<br />
<br />
==== Application notation ====<br />
<br />
Many parentheses can be eliminated using the infix application operator "$"<br />
with lowest priority. Try at least to avoid unnecessary parentheses in<br />
standard infix expression.<br />
<br />
f x : g x ++ h x<br />
<br />
a == 1 && b == 1 || a == 0 && b == 0<br />
<br />
Rather than putting a large final argument in parentheses (with a<br />
distant closing one) consider using "$" instead.<br />
<br />
"f (g x)" becomes "f $ g x" and consecutive applications<br />
"f (g (h x))" can be written as "f $ g $ h x" or "f . g $ h x".<br />
<br />
A function definition like<br />
"f x = g $ h x" can be abbreviated to "f = g . h".<br />
<br />
Note that the final argument may even be an infix- or case expression:<br />
<br />
map id $ c : l<br />
<br />
filter (const True) . map id $ case l of ...<br />
<br />
However, be aware that $-terms cannot be composed further in infix<br />
expressions.<br />
<br />
Probably wrong:<br />
f $ x ++ g $ x<br />
<br />
But the scope of an expression is also limited by the layout rule, so<br />
it is usually safe to use "$" on right hand sides.<br />
<br />
Ok:<br />
do f $ l<br />
++<br />
do g $ l<br />
<br />
Of course "$" can not be used in types. GHC has also some primitive<br />
functions involving the kind "#" that cannot be applied using "$".<br />
<br />
Last warning: always leave spaces around "$" (and other mixfix<br />
operators) since a clash with template haskell is possible.<br />
<br />
(Also write "\ t" instead of "\t" in lambda expressions)<br />
<br />
<br />
==== List Comprehensions ====<br />
<br />
Use these only when "short and sweet". Prefer map, filter, and foldr!<br />
<br />
Instead of:<br />
<br />
[toUpper c | c <- s]<br />
<br />
write:<br />
<br />
map toUpper s<br />
<br />
<br />
Consider:<br />
<br />
[toUpper c | s <- strings, c <- s]<br />
<br />
Here it takes some time for the reader to find out which value depends<br />
on what other value and it is not so clear how many times the interim<br />
values s and c are used. In contrast to that the following can't be clearer:<br />
<br />
map toUpper (concat strings)<br />
<br />
<br />
When using higher order functions you can switch easier to data<br />
structures different from list. Compare:<br />
<br />
map (1+) list<br />
<br />
and:<br />
<br />
Set.map (1+) set<br />
<br />
<br />
==== Types ====<br />
<br />
Prefer proper data types over type synonyms or tuples even if you have<br />
to do more constructing and unpacking. This will make it easier to<br />
supply class instances later on. Don't put class constraints on<br />
a data type, constraints belong only to the functions that manipulate<br />
the data.<br />
<br />
Using type synonyms consistently is difficult over a longer time,<br />
because this is not checked by the compiler. (The types shown by<br />
the compiler may be unpredictable: i.e. FilePath, String or [Char])<br />
<br />
Take care if your data type has many variants (unless it is an<br />
enumeration type.) Don't repeat common parts in every variant since<br />
this will cause code duplication.<br />
<br />
Bad (to handle arguments in sync):<br />
<br />
data Mode f p = Box f p | Diamond f p<br />
<br />
Good (to handle arguments only once):<br />
<br />
data BoxOrDiamond = Box | Diamond<br />
<br />
data Mode f p = Mode BoxOrDiamond f p<br />
<br />
<br />
Consider (bad):<br />
<br />
data Tuple a b = Tuple a b | Undefined<br />
<br />
versus (better):<br />
<br />
data Tuple a b = Tuple a b<br />
<br />
and using:<br />
<br />
Maybe (Tuple a b)<br />
<br />
(or another monad) whenever an undefined result needs to be propagated<br />
<br />
<br />
==== Records ====<br />
<br />
For (large) records avoid the use of the constructor directly and<br />
remember that the order and number of fields may change.<br />
<br />
Take care with (the rare case of) depend polymorphic fields:<br />
<br />
data Fields a = VariantWithTwo<br />
{ field1 :: a<br />
, field2 :: a }<br />
<br />
The type of a value v can not be changed by only setting field1:<br />
<br />
v { field1 = f }<br />
<br />
Better construct a new value:<br />
<br />
VariantWithTwo { field1 = f } -- leaving field2 undefined<br />
<br />
Or use a polymorphic element that is instantiated by updating:<br />
<br />
empty = VariantWithTwo { field1 = [], field2 = [] }<br />
<br />
empty { field1 = [f] }<br />
<br />
Several variants with identical fields may avoid some code duplication<br />
when selecting and updating, though possibly not in a few<br />
depended polymorphic cases.<br />
<br />
However, I doubt if the following is a really good alternative to the<br />
above data Mode with data BoxOrDiamond.<br />
<br />
<br />
data Mode f p =<br />
Box { formula :: f, positions :: p }<br />
| Diamond { formula :: f, positions :: p }<br />
<br />
<br />
==== IO ====<br />
<br />
Try to strictly separate IO, Monad and pure (without do) function<br />
programming (possibly via separate modules).<br />
<br />
Bad:<br />
x <- return y<br />
...<br />
<br />
Good:<br />
let x = y<br />
...<br />
<br />
<br />
Don't use Prelude.interact and make sure your program does not depend<br />
on the (not always obvious) order of evaluation. E.g. don't read and<br />
write to the same file:<br />
<br />
This will fail:<br />
<br />
do s <- readFile f<br />
writeFile f $ 'a' : s<br />
<br />
because of lazy IO! (Writing is starting before reading is finished.)<br />
<br />
==== Trace ====<br />
<br />
Tracing is for debugging purposes only and should not be used as<br />
feedback for the user. Clean code is not cluttered by trace calls.<br />
<br />
<br />
==== Imports ====<br />
<br />
Standard library modules like Char. List, Maybe, Monad, etc should be<br />
imported by their hierarchical module name, i.e. the base package (so<br />
that haddock finds them):<br />
<br />
import Data.List<br />
import Control.Monad<br />
import System.Environment<br />
<br />
The libraries for Set and Map are to be imported qualified:<br />
<br />
import qualified Data.Set as Set<br />
import qualified Data.Map as Map<br />
<br />
<br />
==== Glasgow extensions and Classes ====<br />
<br />
[[Use of language extensions|Stay away from extensions]] as long as possible. Also use classes with<br />
care because soon the desire for overlapping instances (like for lists<br />
and strings) may arise. Then you may want MPTC (multi-parameter type<br />
classes), functional dependencies (FD), undecidable and possibly incoherent<br />
instances and then you are "in the wild" (according to SPJ).<br />
<br />
=== Style in other languages ===<br />
<br />
* [http://www.cs.caltech.edu/~cs20/a/style.html OCaml style]<br />
<br />
=== Final remarks ===<br />
<br />
Despite guidelines, writing "correct code" (without formal proof<br />
support yet) still remains the major challenge. As motivation to<br />
follow these guidelines consider the points that are from the "C++<br />
Coding Standard", where I replaced "C++" with "Haskell".<br />
<br />
Good Points:<br />
<br />
* programmers can go into any code and figure out what's going on<br />
<br />
* new people can get up to speed quickly<br />
<br />
* people new to Haskell are spared the need to develop a personal style and defend it to the death<br />
<br />
* people new to Haskell are spared making the same mistakes over and over again<br />
<br />
* people make fewer mistakes in consistent environments<br />
<br />
* programmers have a common enemy :-)<br />
<br />
Bad Points:<br />
<br />
* the standard is usually stupid because it was made by someone who doesn't understand Haskell<br />
<br />
* the standard is usually stupid because it's not what I do<br />
<br />
* standards reduce creativity<br />
<br />
* standards are unnecessary as long as people are consistent<br />
<br />
* standards enforce too much structure<br />
<br />
* people ignore standards anyway<br />
<br />
== Another guidelines ==<br />
<br />
[https://github.com/tibbe/haskell-style-guide/blob/master/haskell-style.md tibbe/haskell-style-guide]<br />
<br />
<br />
[[Category:Style]]</div>Wizzuphttps://wiki.haskell.org/index.php?title=Programming_guidelines&diff=62800Programming guidelines2019-03-01T06:51:07Z<p>Wizzup: </p>
<hr />
<div>Programming guidelines shall help to make the code of a project better<br />
readable and maintainable by the varying number of contributors.<br />
<br />
It takes some programming experience to develop something like a<br />
personal "coding style" and guidelines only serve as rough shape for<br />
code. Guidelines should be followed by all members working on the<br />
project even if they prefer (or are already used to) different<br />
guidelines.<br />
<br />
These guidelines have been originally set up for the hets-project<br />
[http://www.informatik.uni-bremen.de/cofi/hets/ hets-project] and are<br />
now put on the [http://haskell.org/haskellwiki/ HaskellWiki] gradually<br />
integrating parts of the old hawiki<br />
entries [http://haskell.org/haskellwiki/Things_to_avoid ThingsToAvoid] and<br />
HaskellStyle (hopefully not<br />
hurting someone's copyrights). The other related entry<br />
TipsAndTricks treats more<br />
specific points that are left out here,<br />
<br />
Surely some style choices are a bit arbitrary (or "religious") and<br />
too restrictive with respect to language extensions. Nevertheless I hope<br />
to keep up these guidelines (at least as a basis) for our project<br />
in order to avoid maintaining diverging guidelines. Of course I want<br />
to supply - partly tool-dependent - reasons for certain decisions and<br />
also show alternatives by possibly bad examples. At the time of<br />
writing I use ghc-6.4.1, haddock-0.7 and (GNU-) emacs with the latest<br />
[http://www.haskell.org/haskell-mode/ haskell mode].<br />
<br />
The following quote and links are taken from<br />
HaskellStyle:<br />
<br />
We all have our own ideas about good Haskell style. There's More Than<br />
One Way To Do It. But some ways are better than others.<br />
<br />
Some comments from the GHC team about their internal coding<br />
standards can be found at<br />
http://hackage.haskell.org/trac/ghc/wiki/WorkingConventions<br />
<br />
Also http://research.microsoft.com/~simonpj/papers/haskell-retrospective/<br />
contains some brief comments on syntax and style,<br />
<br />
What now follows are descriptions of program documentation, file<br />
format, naming conventions and good programming practice (adapted form<br />
Matt's C/C++ Programming Guidelines and the Linux kernel coding<br />
style).<br />
<br />
<br />
=== Documentation ===<br />
<br />
<br />
Comments are to be written in application terms (i.e. user's point of<br />
view). Don't use technical terms - that's what the code is for!<br />
<br />
Comments should be written using correct spelling and grammar in complete<br />
sentences with punctation (in English only).<br />
<br />
"Generally, you want your comments to tell WHAT your code does, not HOW.<br />
Also, try to avoid putting comments inside a function body: if the<br />
function is so complex that you need to separately comment parts of it,<br />
you should probably" (... decompose it)<br />
<br />
Put a [http://haskell-haddock.readthedocs.io/en/latest/markup.html haddock comment] on top of every exported function and data type!<br />
Make sure haddock accepts these comments.<br />
<br />
=== File Format ===<br />
<br />
<br />
All Haskell source files start with a haddock header of the form:<br />
<br />
<pre><br />
{- |<br />
Module : <File name or $Header$ to be replaced automatically><br />
Description : <optional short text displayed on contents page><br />
Copyright : (c) <Authors or Affiliations><br />
License : <license><br />
<br />
Maintainer : <email><br />
Stability : unstable | experimental | provisional | stable | frozen<br />
Portability : portable | non-portable (<reason>)<br />
<br />
<module description starting at first column><br />
-}<br />
</pre><br />
<br />
A possible compiler pragma (like {-# LANGUAGE CPP #-}) may precede<br />
this header. The following hierarchical module name must of course<br />
match the file name.<br />
<br />
Make sure that the description is changed to meet the module (if the<br />
header was copied from elsewhere). Insert your email address as maintainer.<br />
<br />
Try to write portable (Haskell98) code. If you use e.g. multi-parameter<br />
type classes and functional dependencies the code becomes<br />
"non-portable (MPTC with FD)".<br />
<br />
The \$Header\$ entry will be automatically expanded.<br />
<br />
Lines should not be longer than 80 (preferably 75)<br />
characters to avoid wrapped lines (for casual readers)!<br />
<br />
Don't leave trailing white space in your code in every line.<br />
<br />
Expand all your tabs to spaces to avoid the danger of wrongly expanding<br />
them (or a different display of tabs versus eight spaces). Possibly put<br />
something like the following in your ~/.emacs file.<br />
<br />
(custom-set-variables '(indent-tabs-mode nil))<br />
<br />
The last character in your file should be a newline! Under solaris<br />
you'll get a warning if this is not the case and sometimes last lines<br />
without newlines are ignored (i.e. "#endif" without newline). Emacs<br />
usually asks for a final newline.<br />
<br />
You may use http://hackage.haskell.org/package/scan to check your file format.<br />
<br />
The whole module should not be too long (about 400 lines)<br />
<br />
Please have a look at the [http://haskell-haddock.readthedocs.io/en/latest/markup.html#the-module-description Haddock module header documentation].<br />
<br />
=== Naming Conventions ===<br />
<br />
<br />
In Haskell types start with capital and functions with lowercase<br />
letters, so only avoid infix identifiers! Defining symbolic infix<br />
identifiers should be left to library writers only.<br />
<br />
(The infix identifier "\\" at the end of a line causes cpp preprocessor<br />
problems.)<br />
<br />
Names (especially global ones) should be descriptive and if you need<br />
long names write them as mixed case words (aka camelCase). (but "tmp"<br />
is to be preferred over "thisVariableIsATemporaryCounter")<br />
<br />
Also in the standard libraries, function names with multiple words are<br />
written using the camelCase convention. Similarly, type, typeclass and<br />
constructor names are written using the StudlyCaps convention.<br />
<br />
Some parts of our code use underlines (without unnecessary uppercase<br />
letters) for long identifiers to better reflect names given with<br />
hyphens in the requirement documentation. Also such names should be<br />
transliterated to camlCase identifiers possibly adding a (consistent)<br />
suffix or prefix to avoid conflicts with keywords. However, instead of<br />
a recurring prefix or suffix you may consider to use qualified imports<br />
and names.<br />
<br />
<br />
=== Good Programming Practice ===<br />
<br />
<br />
"Functions should be short and sweet, and do just one thing. They should<br />
fit on one or two screenfuls of text (the ISO/ANSI screen size is 80x24,<br />
as we all know), and do one thing and do that well."<br />
<br />
Most haskell functions should be at most a few lines, only case<br />
expression over large data types (that should be avoided, too) may need<br />
corresponding space.<br />
<br />
The code should be succinct (though not obfuscated), readable and easy to<br />
maintain (after unforeseeable changes). Don't exploit exotic language<br />
features without good reason.<br />
<br />
It's not fixed how deep you indent (4 or 8 chars). You can break the<br />
line after "do", "let", "where", and "case .. of". Make sure that<br />
renamings don't destroy your layout. (If you get too far to the right,<br />
the code is unreadable anyway and needs to be decomposed.)<br />
<br />
Bad:<br />
case foo of Foo -> "Foo"<br />
Bar -> "Bar"<br />
Good:<br />
case <longer expression> of<br />
Foo -> "Foo"<br />
Bar -> "Bar"<br />
<br />
Avoid the notation with braces and semicolons since the layout rule<br />
forces you to properly align your alternatives.<br />
<br />
Respect compiler warnings. Supply type signatures, avoid shadowing and<br />
unused variables. Particularly avoid non-exhaustive and<br />
overlapping patterns. Missing unreachable cases can be filled in using<br />
"error" with a fixed string "<ModuleName>.<function>" to indicate the<br />
error position (in case the impossible should happen). Don't invest<br />
time to "show" the offending value, only do this temporarily when<br />
debugging the code.<br />
<br />
Don't leave unused or commented-out code in your files! Readers don't<br />
know what to think of it.<br />
<br />
<br />
<br />
==== Partial functions ====<br />
<br />
For partial functions do document their preconditions (if not obvious)<br />
and make sure that partial functions are only called when<br />
preconditions are obviously fulfilled (i.e. by a case statement or a<br />
previous test). Particularly the call of "head" should be used with<br />
care or (even better) be made obsolete by a case statement.<br />
<br />
Usually a case statement (and the import of isJust and fromJust from<br />
Data.[[Maybe]]) can be avoided by using the "maybe" function:<br />
<br />
maybe (error "<ModuleName>.<function>") id $ Map.lookup key map<br />
<br />
Generally we require you to be more explicit about failure<br />
cases. Surely a missing (or an irrefutable) pattern would precisely<br />
report the position of a runtime error, but these are not so obvious<br />
when reading the code.<br />
<br />
==== Let or where expressions ====<br />
<br />
Do avoid mixing and nesting "let" and "where". (I prefer the<br />
expression-stylistic "let".) Use auxiliary top-level functions that<br />
you do not export. Export lists also support the detection of unused<br />
functions.<br />
<br />
<br />
==== Code reuse ====<br />
<br />
If you notice that you're doing the same task again, try to generalize<br />
it in order to avoid duplicate code. It is frustrating to change the<br />
same error in several places.<br />
<br />
<br />
==== Application notation ====<br />
<br />
Many parentheses can be eliminated using the infix application operator "$"<br />
with lowest priority. Try at least to avoid unnecessary parentheses in<br />
standard infix expression.<br />
<br />
f x : g x ++ h x<br />
<br />
a == 1 && b == 1 || a == 0 && b == 0<br />
<br />
Rather than putting a large final argument in parentheses (with a<br />
distant closing one) consider using "$" instead.<br />
<br />
"f (g x)" becomes "f $ g x" and consecutive applications<br />
"f (g (h x))" can be written as "f $ g $ h x" or "f . g $ h x".<br />
<br />
A function definition like<br />
"f x = g $ h x" can be abbreviated to "f = g . h".<br />
<br />
Note that the final argument may even be an infix- or case expression:<br />
<br />
map id $ c : l<br />
<br />
filter (const True) . map id $ case l of ...<br />
<br />
However, be aware that $-terms cannot be composed further in infix<br />
expressions.<br />
<br />
Probably wrong:<br />
f $ x ++ g $ x<br />
<br />
But the scope of an expression is also limited by the layout rule, so<br />
it is usually safe to use "$" on right hand sides.<br />
<br />
Ok:<br />
do f $ l<br />
++<br />
do g $ l<br />
<br />
Of course "$" can not be used in types. GHC has also some primitive<br />
functions involving the kind "#" that cannot be applied using "$".<br />
<br />
Last warning: always leave spaces around "$" (and other mixfix<br />
operators) since a clash with template haskell is possible.<br />
<br />
(Also write "\ t" instead of "\t" in lambda expressions)<br />
<br />
<br />
==== List Comprehensions ====<br />
<br />
Use these only when "short and sweet". Prefer map, filter, and foldr!<br />
<br />
Instead of:<br />
<br />
[toUpper c | c <- s]<br />
<br />
write:<br />
<br />
map toUpper s<br />
<br />
<br />
Consider:<br />
<br />
[toUpper c | s <- strings, c <- s]<br />
<br />
Here it takes some time for the reader to find out which value depends<br />
on what other value and it is not so clear how many times the interim<br />
values s and c are used. In contrast to that the following can't be clearer:<br />
<br />
map toUpper (concat strings)<br />
<br />
<br />
When using higher order functions you can switch easier to data<br />
structures different from list. Compare:<br />
<br />
map (1+) list<br />
<br />
and:<br />
<br />
Set.map (1+) set<br />
<br />
<br />
==== Types ====<br />
<br />
Prefer proper data types over type synonyms or tuples even if you have<br />
to do more constructing and unpacking. This will make it easier to<br />
supply class instances later on. Don't put class constraints on<br />
a data type, constraints belong only to the functions that manipulate<br />
the data.<br />
<br />
Using type synonyms consistently is difficult over a longer time,<br />
because this is not checked by the compiler. (The types shown by<br />
the compiler may be unpredictable: i.e. FilePath, String or [Char])<br />
<br />
Take care if your data type has many variants (unless it is an<br />
enumeration type.) Don't repeat common parts in every variant since<br />
this will cause code duplication.<br />
<br />
Bad (to handle arguments in sync):<br />
<br />
data Mode f p = Box f p | Diamond f p<br />
<br />
Good (to handle arguments only once):<br />
<br />
data BoxOrDiamond = Box | Diamond<br />
<br />
data Mode f p = Mode BoxOrDiamond f p<br />
<br />
<br />
Consider (bad):<br />
<br />
data Tuple a b = Tuple a b | Undefined<br />
<br />
versus (better):<br />
<br />
data Tuple a b = Tuple a b<br />
<br />
and using:<br />
<br />
Maybe (Tuple a b)<br />
<br />
(or another monad) whenever an undefined result needs to be propagated<br />
<br />
<br />
==== Records ====<br />
<br />
For (large) records avoid the use of the constructor directly and<br />
remember that the order and number of fields may change.<br />
<br />
Take care with (the rare case of) depend polymorphic fields:<br />
<br />
data Fields a = VariantWithTwo<br />
{ field1 :: a<br />
, field2 :: a }<br />
<br />
The type of a value v can not be changed by only setting field1:<br />
<br />
v { field1 = f }<br />
<br />
Better construct a new value:<br />
<br />
VariantWithTwo { field1 = f } -- leaving field2 undefined<br />
<br />
Or use a polymorphic element that is instantiated by updating:<br />
<br />
empty = VariantWithTwo { field1 = [], field2 = [] }<br />
<br />
empty { field1 = [f] }<br />
<br />
Several variants with identical fields may avoid some code duplication<br />
when selecting and updating, though possibly not in a few<br />
depended polymorphic cases.<br />
<br />
However, I doubt if the following is a really good alternative to the<br />
above data Mode with data BoxOrDiamond.<br />
<br />
<br />
data Mode f p =<br />
Box { formula :: f, positions :: p }<br />
| Diamond { formula :: f, positions :: p }<br />
<br />
<br />
==== IO ====<br />
<br />
Try to strictly separate IO, Monad and pure (without do) function<br />
programming (possibly via separate modules).<br />
<br />
Bad:<br />
x <- return y<br />
...<br />
<br />
Good:<br />
let x = y<br />
...<br />
<br />
<br />
Don't use Prelude.interact and make sure your program does not depend<br />
on the (not always obvious) order of evaluation. E.g. don't read and<br />
write to the same file:<br />
<br />
This will fail:<br />
<br />
do s <- readFile f<br />
writeFile f $ 'a' : s<br />
<br />
because of lazy IO! (Writing is starting before reading is finished.)<br />
<br />
==== Trace ====<br />
<br />
Tracing is for debugging purposes only and should not be used as<br />
feedback for the user. Clean code is not cluttered by trace calls.<br />
<br />
<br />
==== Imports ====<br />
<br />
Standard library modules like Char. List, Maybe, Monad, etc should be<br />
imported by their hierarchical module name, i.e. the base package (so<br />
that haddock finds them):<br />
<br />
import Data.List<br />
import Control.Monad<br />
import System.Environment<br />
<br />
The libraries for Set and Map are to be imported qualified:<br />
<br />
import qualified Data.Set as Set<br />
import qualified Data.Map as Map<br />
<br />
<br />
==== Glasgow extensions and Classes ====<br />
<br />
[[Use of language extensions|Stay away from extensions]] as long as possible. Also use classes with<br />
care because soon the desire for overlapping instances (like for lists<br />
and strings) may arise. Then you may want MPTC (multi-parameter type<br />
classes), functional dependencies (FD), undecidable and possibly incoherent<br />
instances and then you are "in the wild" (according to SPJ).<br />
<br />
=== Style in other languages ===<br />
<br />
* [http://www.cs.caltech.edu/~cs20/a/style.html OCaml style]<br />
<br />
=== Final remarks ===<br />
<br />
Despite guidelines, writing "correct code" (without formal proof<br />
support yet) still remains the major challenge. As motivation to<br />
follow these guidelines consider the points that are from the "C++<br />
Coding Standard", where I replaced "C++" with "Haskell".<br />
<br />
Good Points:<br />
<br />
* programmers can go into any code and figure out what's going on<br />
<br />
* new people can get up to speed quickly<br />
<br />
* people new to Haskell are spared the need to develop a personal style and defend it to the death<br />
<br />
* people new to Haskell are spared making the same mistakes over and over again<br />
<br />
* people make fewer mistakes in consistent environments<br />
<br />
* programmers have a common enemy :-)<br />
<br />
Bad Points:<br />
<br />
* the standard is usually stupid because it was made by someone who doesn't understand Haskell<br />
<br />
* the standard is usually stupid because it's not what I do<br />
<br />
* standards reduce creativity<br />
<br />
* standards are unnecessary as long as people are consistent<br />
<br />
* standards enforce too much structure<br />
<br />
* people ignore standards anyway<br />
<br />
== Another guidelines ==<br />
<br />
[https://github.com/tibbe/haskell-style-guide/blob/master/haskell-style.md tibbe/haskell-style-guide]<br />
<br />
<br />
[[Category:Style]]</div>Wizzuphttps://wiki.haskell.org/index.php?title=Blog_articles&diff=62798Blog articles2019-02-27T11:34:04Z<p>Wizzup: use internal links instead of external links</p>
<hr />
<div>Many areas of Haskell have been explored in the form of blog posts. This<br />
page collects the best of those articles from across the web. Due to the<br />
vast amount of material, this page is divided into sub-categories:<br />
<br />
New material is posted to the [http://www.reddit.com/r/haskell/ Haskell Reddit] and [http://www.dohaskell.com/ dohaskell]<br />
<br />
== Introductory material ==<br />
<br />
* [[/Introductions|Introductions to Haskell]]<br />
* [[/Comparisons|Comparing Haskell to other languages]]<br />
* [[/Functional_programming|Functional programming in general]]<br />
* [[/Exercises|Small programming exercises]]<br />
<br />
== Specific topics ==<br />
<br />
* [[/Algorithms|Algorithms and techniques]]<br />
* [[/Data|Data and control structures]]<br />
* [[/Databases|Databases in Haskell]]<br />
* [[/Errors|Error handling and exceptions]]<br />
* [[/GUIs|GUIs in Haskell]]<br />
* [[/Graphics|Graphics]]<br />
* [[/Web|HTML and XML and the Web]]<br />
* [[/Hardware|Hardware and robots]]<br />
* [[/Language|Haskell language features]]<br />
* [[/Performance|High performance Haskell]]<br />
* [[/IO|IO in Haskell]]<br />
* [[/FFI|The FFI: interfaces to other languages]]<br />
* [[/Libraries|Libraries and packages]]<br />
* [[/Mathematics|Mathematics and Haskell]]<br />
* [[/Monads|Monads, Comonads, Arrows]]<br />
* [[/Network|Networking]]<br />
* [[/Parallel|Parallel and concurrent programming]]<br />
* [[/Parsing|Parsing, regular expressions]]<br />
* [[/EDSLs|Domain specific languages and code generation]]<br />
* [[/Types|Programming with types]]<br />
* [[/Testing|Testing, correctness and proofs]]<br />
<br />
== Further reading ==<br />
<br />
Further material on these topics is available in [http://en.wikibooks.org/wiki/Haskell The Haskell Wikibook]<br />
<br />
For libraries divided into similar topics, see:<br />
<br />
* [http://hackage.haskell.org/packages/archive/pkg-list.html the Hackage database]<br />
* [[Applications and libraries]]<br />
<br />
For in-depth research into these topics:<br />
<br />
* [[Research papers]]<br />
<br />
[[Category:Tutorials]]</div>Wizzuphttps://wiki.haskell.org/index.php?title=Let%27s_Play_Free_Games&diff=62797Let's Play Free Games2019-02-27T04:43:29Z<p>Wizzup: remove dead link</p>
<hr />
<div>== A Brainiac style game using symbols from the Haskell World ==<br />
<br><br />
<br />
<center> [[Image:Haskellgame-pic-small.gif]] </center><br />
<br />
<br />
Yes, the site from the back is the site of our faculty from Bacau. <br />
<br><br />
Stiinte - means science <br><br />
ub - means "V. Alecsandri" University of Bacau <br><br />
ro - Romania <br><br />
<br />
<!-- <br />
http://www.haskell.org/sitewiki/images/7/72/HaskellGame.bin Right click -> Save Link As -> Save As HaskellGame.exe<br />
--!><br />
<br />
I hope everybody will recognize the symbols of some important activities from the Haskell community. <br />
<br />
*The Monad Reader,<br />
*Monad, <br />
*Haskell Community and<br />
*Hcar ...and more<br />
<br />
Developing this page ...</div>Wizzuphttps://wiki.haskell.org/index.php?title=Base_package&diff=62796Base package2019-02-27T04:28:37Z<p>Wizzup: /* Versions */</p>
<hr />
<div>The '''base package''' contains the [[Prelude]] and its support libraries, and a large collection of useful libraries ranging from data structures to parsing combinators and debugging utilities. It is specific to the GHC implementation of Haskell.<br />
<br />
This package includes the following: <br />
<br />
*[[Arrays]]<br />
<br />
*[[Arrow]]s<br />
<br />
*[[Functor]]s<br />
<br />
*[[Maybe]]<br />
<br />
*[[Monad]]s<br />
<br />
and many others.<br />
<br />
== Versions ==<br />
<br />
The [https://hackage.haskell.org/package/base base] package is shipped alongside the GHC compiler itself, but version numbers for the base package do not match the GHC version number. Here is a table indicating which base package versions ship with which GHC.<br />
<br />
Data is taken from GHC release notes, and, since base 4.7.0.0, the [https://hackage.haskell.org/package/base/changelog changelog.md] file in the base package's source code. Only GHC versions in which the base package's version number was bumped are listed here.<br />
<br />
On the GHC Trac wiki, one can find a more comprehensive [https://ghc.haskell.org/trac/ghc/wiki/Commentary/Libraries/VersionHistory table of versions] that includes ''all'' boot libraries.<br />
<br />
{|<br />
|-<br />
! GHC version<br />
! base version<br />
|-<br />
| 6.10.1 (Nov 2008)<br />
| 4.0.0.0<br />
|-<br />
| 6.10.2 (Apr 2009)<br />
| 4.1.0.0<br />
|-<br />
| 6.12.1 (Dec 2009)<br />
| 4.2.0.0<br />
|-<br />
| 6.12.2 (Apr 2010)<br />
| 4.2.0.1<br />
|-<br />
| 6.12.3 (Jun 2010)<br />
| 4.2.0.2<br />
|-<br />
| 7.0.1 (Nov 2010)<br />
| 4.3.0.0<br />
|-<br />
| 7.0.2 (Mar 2011)<br />
| 4.3.1.0<br />
|-<br />
| 7.2.1 (Aug 2011)<br />
| 4.4.0.0<br />
|-<br />
| 7.2.2 (Nov 2011)<br />
| 4.4.1.0<br />
|-<br />
| 7.4.1 (Feb 2012)<br />
| 4.5.0.0<br />
|-<br />
| 7.4.2 (Jun 2012)<br />
| 4.5.1.0<br />
|-<br />
| 7.6.1 (Sep 2012)<br />
| 4.6.0.0<br />
|-<br />
| 7.6.2 (Jan 2013)<br />
| 4.6.0.1<br />
|-<br />
| 7.8.1 (Apr 2014)<br />
| 4.7.0.0<br />
|-<br />
| 7.8.3 (Jul 2014)<br />
| 4.7.0.1<br />
|-<br />
| 7.8.4 (Dec 2014)<br />
| 4.7.0.2<br />
|-<br />
| 7.10.1 (Apr 2015)<br />
| 4.8.0.0<br />
|-<br />
| 7.10.2 (Jul 2015)<br />
| 4.8.1.0<br />
|-<br />
| 7.10.3 (Dec 2015)<br />
| 4.8.2.0<br />
|-<br />
| 8.0.1 (May 2016)<br />
| 4.9.0.0<br />
|-<br />
| 8.0.2 (Jan 2017)<br />
| 4.9.1.0<br />
|-<br />
| 8.2.1 (Jul 2017)<br />
| 4.10.0.0<br />
|-<br />
| 8.2.2 (Nov 2017)<br />
| 4.10.1.0<br />
|-<br />
| 8.4.1 (Mar 2018)<br />
| 4.11.0.0<br />
|-<br />
| 8.4.2 (Apr 2018)<br />
| 4.11.1.0<br />
<!--<br />
|-<br />
| 8.4.3 (May 2018)<br />
| 4.11.1.0<br />
--><br />
|-<br />
| 8.6.1 (August 2018)<br />
| 4.12.0.0<br />
|}<br />
<br />
See also the [https://hackage.haskell.org/package/base hackage page for the base package].<br />
<br />
[[Category:Standard packages]]</div>Wizzuphttps://wiki.haskell.org/index.php?title=Base_package&diff=62795Base package2019-02-27T04:21:27Z<p>Wizzup: /* Versions */</p>
<hr />
<div>The '''base package''' contains the [[Prelude]] and its support libraries, and a large collection of useful libraries ranging from data structures to parsing combinators and debugging utilities. It is specific to the GHC implementation of Haskell.<br />
<br />
This package includes the following: <br />
<br />
*[[Arrays]]<br />
<br />
*[[Arrow]]s<br />
<br />
*[[Functor]]s<br />
<br />
*[[Maybe]]<br />
<br />
*[[Monad]]s<br />
<br />
and many others.<br />
<br />
== Versions ==<br />
<br />
The [https://hackage.haskell.org/package/base base] package is shipped alongside the GHC compiler itself, but version numbers for the base package do not match the GHC version number. Here is a table indicating which base package versions ship with which GHC.<br />
<br />
Data is taken from GHC release notes, and, since base 4.7.0.0, the changelog.md file in the base package's source code. Only GHC versions in which the base package's version number was bumped are listed here.<br />
<br />
On the GHC Trac wiki, one can find a more comprehensive [https://ghc.haskell.org/trac/ghc/wiki/Commentary/Libraries/VersionHistory table of versions that includes ''all'' boot libraries].<br />
<br />
{|<br />
|-<br />
! GHC version<br />
! base version<br />
|-<br />
| 6.10.1 (Nov 2008)<br />
| 4.0.0.0<br />
|-<br />
| 6.10.2 (Apr 2009)<br />
| 4.1.0.0<br />
|-<br />
| 6.12.1 (Dec 2009)<br />
| 4.2.0.0<br />
|-<br />
| 6.12.2 (Apr 2010)<br />
| 4.2.0.1<br />
|-<br />
| 6.12.3 (Jun 2010)<br />
| 4.2.0.2<br />
|-<br />
| 7.0.1 (Nov 2010)<br />
| 4.3.0.0<br />
|-<br />
| 7.0.2 (Mar 2011)<br />
| 4.3.1.0<br />
|-<br />
| 7.2.1 (Aug 2011)<br />
| 4.4.0.0<br />
|-<br />
| 7.2.2 (Nov 2011)<br />
| 4.4.1.0<br />
|-<br />
| 7.4.1 (Feb 2012)<br />
| 4.5.0.0<br />
|-<br />
| 7.4.2 (Jun 2012)<br />
| 4.5.1.0<br />
|-<br />
| 7.6.1 (Sep 2012)<br />
| 4.6.0.0<br />
|-<br />
| 7.6.2 (Jan 2013)<br />
| 4.6.0.1<br />
|-<br />
| 7.8.1 (Apr 2014)<br />
| 4.7.0.0<br />
|-<br />
| 7.8.3 (Jul 2014)<br />
| 4.7.0.1<br />
|-<br />
| 7.8.4 (Dec 2014)<br />
| 4.7.0.2<br />
|-<br />
| 7.10.1 (Apr 2015)<br />
| 4.8.0.0<br />
|-<br />
| 7.10.2 (Jul 2015)<br />
| 4.8.1.0<br />
|-<br />
| 7.10.3 (Dec 2015)<br />
| 4.8.2.0<br />
|-<br />
| 8.0.1 (May 2016)<br />
| 4.9.0.0<br />
|-<br />
| 8.0.2 (Jan 2017)<br />
| 4.9.1.0<br />
|-<br />
| 8.2.1 (Jul 2017)<br />
| 4.10.0.0<br />
|-<br />
| 8.2.2 (Nov 2017)<br />
| 4.10.1.0<br />
|-<br />
| 8.4.1 (Mar 2018)<br />
| 4.11.0.0<br />
|-<br />
| 8.4.2 (Apr 2018)<br />
| 4.11.1.0<br />
|-<br />
| 8.4.3 (May 2018)<br />
| 4.11.1.0<br />
|-<br />
| 8.6.1 (August 2018)<br />
| [https://hackage.haskell.org/package/base-4.12.0.0/changelog 4.12.0.0]<br />
|}<br />
<br />
See also the [https://hackage.haskell.org/package/base hackage page for the base package].<br />
<br />
[[Category:Standard packages]]</div>Wizzuphttps://wiki.haskell.org/index.php?title=99_questions/95_to_99&diff=6277999 questions/95 to 992019-02-16T07:36:57Z<p>Wizzup: unify ghci prompts</p>
<hr />
<div>__NOTOC__<br />
<br />
This is part of [[H-99:_Ninety-Nine_Haskell_Problems|Ninety-Nine Haskell Problems]], based on [https://prof.ti.bfh.ch/hew1/informatik3/prolog/p-99/ Ninety-Nine Prolog Problems].<br />
<br />
== Problem 95 ==<br />
<br />
(**) English number words<br />
<br />
On financial documents, like cheques, numbers must sometimes be written in full words. Example: 175 must be written as one-seven-five. Write a predicate full-words/1 to print (non-negative) integer numbers in full words.<br />
<br />
Example in Haskell:<br />
<br />
<haskell><br />
λ> fullWords 175<br />
one-seven-five<br />
</haskell><br />
<br />
[[99 questions/Solutions/95 | Solutions]]<br />
<br />
<br />
== Problem 96 ==<br />
<br />
(**) Syntax checker<br />
<br />
In a certain programming language (Ada) identifiers are defined by the syntax diagram below.<br />
<br />
https://prof.ti.bfh.ch/hew1/informatik3/prolog/p-99/p96.gif<br />
<br />
Transform the syntax diagram into a system of syntax diagrams which do not contain loops; i.e. which are purely recursive. Using these modified diagrams, write a predicate identifier/1 that can check whether or not a given string is a legal identifier.<br />
<br />
Example in Prolog:<br />
<br />
<pre><br />
% identifier(Str) :- Str is a legal identifier <br />
</pre><br />
<br />
Example in Haskell:<br />
<br />
<haskell><br />
λ> identifier "this-is-a-long-identifier"<br />
True<br />
λ> identifier "this-ends-in-" <br />
False<br />
λ> identifier "two--hyphens" <br />
False<br />
</haskell><br />
<br />
[[99 questions/Solutions/96 | Solutions]]<br />
<br />
<br />
== Problem 97 ==<br />
<br />
(**) Sudoku<br />
<br />
Sudoku puzzles go like this:<br />
<br />
<pre><br />
Problem statement Solution<br />
<br />
. . 4 | 8 . . | . 1 7 9 3 4 | 8 2 5 | 6 1 7 <br />
| | | |<br />
6 7 . | 9 . . | . . . 6 7 2 | 9 1 4 | 8 5 3<br />
| | | |<br />
5 . 8 | . 3 . | . . 4 5 1 8 | 6 3 7 | 9 2 4<br />
--------+---------+-------- --------+---------+--------<br />
3 . . | 7 4 . | 1 . . 3 2 5 | 7 4 8 | 1 6 9<br />
| | | |<br />
. 6 9 | . . . | 7 8 . 4 6 9 | 1 5 3 | 7 8 2<br />
| | | |<br />
. . 1 | . 6 9 | . . 5 7 8 1 | 2 6 9 | 4 3 5<br />
--------+---------+-------- --------+---------+--------<br />
1 . . | . 8 . | 3 . 6 1 9 7 | 5 8 2 | 3 4 6<br />
| | | |<br />
. . . | . . 6 | . 9 1 8 5 3 | 4 7 6 | 2 9 1<br />
| | | |<br />
2 4 . | . . 1 | 5 . . 2 4 6 | 3 9 1 | 5 7 8<br />
</pre> <br />
<br />
Every spot in the puzzle belongs to a (horizontal) row and a (vertical) column, as well as to one single 3x3 square (which we call "square" for short). At the beginning, some of the spots carry a single-digit number between 1 and 9. The problem is to fill the missing spots with digits in such a way that every number between 1 and 9 appears exactly once in each row, in each column, and in each square. <br />
<br />
[[99 questions/Solutions/97 | Solutions]]<br />
<br />
<br />
== Problem 98 ==<br />
<br />
(***) Nonograms<br />
<br />
Around 1994, a certain kind of puzzle was very popular in England. The "Sunday Telegraph" newspaper wrote: "Nonograms are puzzles from Japan and are currently published each week only in The Sunday Telegraph. Simply use your logic and skill to complete the grid and reveal a picture or diagram." As a Prolog programmer, you are in a better situation: you can have your computer do the work! Just write a little program ;-).<br />
<br />
The puzzle goes like this: Essentially, each row and column of a rectangular bitmap is annotated with the respective lengths of its distinct strings of occupied cells. The person who solves the puzzle must complete the bitmap given only these lengths.<br />
<br />
Problem statement: Solution:<br />
<br />
|_|_|_|_|_|_|_|_| 3 |_|X|X|X|_|_|_|_| 3 <br />
|_|_|_|_|_|_|_|_| 2 1 |X|X|_|X|_|_|_|_| 2 1 <br />
|_|_|_|_|_|_|_|_| 3 2 |_|X|X|X|_|_|X|X| 3 2 <br />
|_|_|_|_|_|_|_|_| 2 2 |_|_|X|X|_|_|X|X| 2 2 <br />
|_|_|_|_|_|_|_|_| 6 |_|_|X|X|X|X|X|X| 6 <br />
|_|_|_|_|_|_|_|_| 1 5 |X|_|X|X|X|X|X|_| 1 5 <br />
|_|_|_|_|_|_|_|_| 6 |X|X|X|X|X|X|_|_| 6 <br />
|_|_|_|_|_|_|_|_| 1 |_|_|_|_|X|_|_|_| 1 <br />
|_|_|_|_|_|_|_|_| 2 |_|_|_|X|X|_|_|_| 2 <br />
1 3 1 7 5 3 4 3 1 3 1 7 5 3 4 3 <br />
2 1 5 1 2 1 5 1 <br />
<br />
<br />
For the example above, the problem can be stated as the two lists [[3],[2,1],[3,2],[2,2],[6],[1,5],[6],[1],[2]] and [[1,2],[3,1],[1,5],[7,1],[5],[3],[4],[3]] which give the "solid" lengths of the rows and columns, top-to-bottom and left-to-right, respectively. Published puzzles are larger than this example, e.g. 25 x 20, and apparently always have unique solutions.<br />
<br />
Example in Haskell:<br />
<br />
<haskell><br />
λ> putStr $ nonogram [[3],[2,1],[3,2],[2,2],[6],[1,5],[6],[1],[2]] [[1,2],[3,1],[1,5],[7,1],[5],[3],[4],[3]]<br />
|_|X|X|X|_|_|_|_| 3<br />
|X|X|_|X|_|_|_|_| 2 1<br />
|_|X|X|X|_|_|X|X| 3 2<br />
|_|_|X|X|_|_|X|X| 2 2<br />
|_|_|X|X|X|X|X|X| 6<br />
|X|_|X|X|X|X|X|_| 1 5<br />
|X|X|X|X|X|X|_|_| 6<br />
|_|_|_|_|X|_|_|_| 1<br />
|_|_|_|X|X|_|_|_| 2<br />
1 3 1 7 5 3 4 3<br />
2 1 5 1 <br />
</haskell><br />
<br />
[[99 questions/Solutions/98 | Solutions]]<br />
<br />
<br />
== Problem 99 ==<br />
<br />
(***) Crossword puzzle<br />
<br />
Given an empty (or almost empty) framework of a crossword puzzle and a set of words. The problem is to place the words into the framework.<br />
<br />
https://prof.ti.bfh.ch/hew1/informatik3/prolog/p-99/p99.gif<br />
<br />
The particular crossword puzzle is specified in a text file which first lists the words (one word per line) in an arbitrary order. Then, after an empty line, the crossword framework is defined. In this framework specification, an empty character location is represented by a dot (.). In order to make the solution easier, character locations can also contain predefined character values. The puzzle above is defined in the file [https://sites.google.com/site/prologsite/prolog-problems/7/solutions-7/p7_09a.dat?attredirects=0&d=1 p7_09a.dat], other examples are [https://sites.google.com/site/prologsite/prolog-problems/7/solutions-7/p7_09b.dat?attredirects=0&d=1 p7_09b.dat] and [https://sites.google.com/site/prologsite/prolog-problems/7/solutions-7/p7_09d.dat?attredirects=0&d=1 p7_09d.dat]. There is also an example of a puzzle ([https://sites.google.com/site/prologsite/prolog-problems/7/solutions-7/p7_09c.dat?attredirects=0&d=1 p7_09c.dat]) which does not have a solution.<br />
<br />
Words are strings (character lists) of at least two characters. A horizontal or vertical sequence of character places in the crossword puzzle framework is called a site. Our problem is to find a compatible way of placing words onto sites.<br />
<br />
Hints: (1) The problem is not easy. You will need some time to thoroughly understand it. So, don't give up too early! And remember that the objective is a clean solution, not just a quick-and-dirty hack!<br />
<br />
(2) Reading the data file is a tricky problem for which a solution is provided in the file [https://sites.google.com/site/prologsite/prolog-problems/7/solutions-7/p7_09-readfile.pl?attredirects=0&d=1 p7_09-readfile.pl]. See the predicate read_lines/2.<br />
<br />
(3) For efficiency reasons it is important, at least for larger puzzles, to sort the words and the sites in a particular order. For this part of the problem, the solution of P28 may be very helpful. <br />
<br />
Example in Haskell:<br />
<br />
<pre><br />
ALPHA<br />
ARES<br />
POPPY<br />
<br />
.<br />
.<br />
.....<br />
. .<br />
. .<br />
.<br />
</pre><br />
<br />
<haskell><br />
λ> solve $ readCrossword "ALPHA\nARES\nPOPPY\n\n . \n . \n.....\n . .\n . .\n .\n"<br />
<br />
[[((3,1),'A'),((3,2),'L'),((3,3),'P'),((3,4),'H'),((3,5),'A'),((1,3),'P'),((2,3)<br />
,'O'),((3,3),'P'),((4,3),'P'),((5,3),'Y'),((3,5),'A'),((4,5),'R'),((5,5),'E'),((<br />
6,5),'S')]]<br />
</haskell><br />
<br />
[[99 questions/Solutions/99 | Solutions]]<br />
<br />
<br />
[[Category:Tutorials]]</div>Wizzuphttps://wiki.haskell.org/index.php?title=99_questions/90_to_94&diff=6277899 questions/90 to 942019-02-16T07:32:37Z<p>Wizzup: /* Problem 91 */</p>
<hr />
<div>__NOTOC__<br />
<br />
This is part of [[H-99:_Ninety-Nine_Haskell_Problems|Ninety-Nine Haskell Problems]], based on [https://prof.ti.bfh.ch/hew1/informatik3/prolog/p-99/ Ninety-Nine Prolog Problems].<br />
<br />
If you want to work on one of these, put your name in the block so we know someone's working on it. Then, change n in your block to the appropriate problem number, and fill in the <Problem description>,<example in Haskell>,<solution in haskell> and <description of implementation> fields. <br />
<br />
== Problem 90 ==<br />
<br />
(**) Eight queens problem<br />
<br />
This is a classical problem in computer science. The objective is to place eight queens on a chessboard so that no two queens are attacking each other; i.e., no two queens are in the same row, the same column, or on the same diagonal.<br />
<br />
Hint: Represent the positions of the queens as a list of numbers 1..N. Example: [4,2,7,3,6,8,5,1] means that the queen in the first column is in row 4, the queen in the second column is in row 2, etc. Use the generate-and-test paradigm.<br />
<br />
Example in Haskell:<br />
<br />
<haskell><br />
λ> length (queens 8)<br />
92<br />
λ> head (queens 8)<br />
[1,5,8,6,3,7,2,4]<br />
</haskell><br />
<br />
[[99 questions/Solutions/90 | Solutions]]<br />
<br />
<br />
== Problem 91 ==<br />
<br />
(**) Knight's tour<br />
<br />
Another famous problem is this one: How can a knight jump on an NxN chessboard in such a way that it visits every square exactly once? A set of solutions is given on the [[The_Knights_Tour]] page.<br />
<br />
Hints: Represent the squares by pairs of their coordinates of the form X/Y, where both X and Y are integers between 1 and N. (Note that '/' is just a convenient functor, not division!) Define the relation jump(N,X/Y,U/V) to express the fact that a knight can jump from X/Y to U/V on a NxN chessboard. And finally, represent the solution of our problem as a list of N*N knight positions (the knight's tour).<br />
<br />
There are two variants of this problem:<br />
# find a tour ending at a particular square<br />
# find a circular tour, ending a knight's jump from the start (clearly it doesn't matter where you start, so choose (1,1))<br />
<br />
Example in Haskell:<br />
<br />
<haskell><br />
λ> head $ knightsTo 8 (1,1)<br />
[(2,7),(3,5),(5,6),(4,8),(3,6),(4,4),(6,5),(4,6),<br />
(5,4),(7,5),(6,3),(5,5),(4,3),(2,4),(1,6),(2,8),<br />
(4,7),(6,8),(8,7),(6,6),(4,5),(6,4),(5,2),(7,1),<br />
(8,3),(6,2),(8,1),(7,3),(8,5),(7,7),(5,8),(3,7),<br />
(1,8),(2,6),(3,4),(1,5),(2,3),(3,1),(1,2),(3,3),<br />
(1,4),(2,2),(4,1),(5,3),(7,4),(8,2),(6,1),(4,2),<br />
(2,1),(1,3),(2,5),(1,7),(3,8),(5,7),(7,8),(8,6),<br />
(6,7),(8,8),(7,6),(8,4),(7,2),(5,1),(3,2),(1,1)]<br />
λ> head $ closedKnights 8 <br />
[(1,1),(3,2),(1,3),(2,1),(3,3),(5,4),(6,6),(4,5),<br />
(2,6),(1,8),(3,7),(5,8),(4,6),(2,5),(4,4),(5,6),<br />
(6,4),(8,5),(7,7),(6,5),(5,3),(6,1),(4,2),(6,3),<br />
(8,2),(7,4),(5,5),(3,4),(1,5),(2,7),(4,8),(3,6),<br />
(1,7),(3,8),(5,7),(7,8),(8,6),(6,7),(8,8),(7,6),<br />
(8,4),(7,2),(5,1),(4,3),(3,5),(1,4),(2,2),(4,1),<br />
(6,2),(8,1),(7,3),(5,2),(7,1),(8,3),(7,5),(8,7),<br />
(6,8),(4,7),(2,8),(1,6),(2,4),(1,2),(3,1),(2,3)]<br />
</haskell><br />
<br />
[[99 questions/Solutions/91 | Solutions]]<br />
<br />
== Problem 92 ==<br />
<br />
(***) Von Koch's conjecture<br />
<br />
Several years ago I met a mathematician who was intrigued by a problem for which he didn't know a solution. His name was Von Koch, and I don't know whether the problem has been solved since.<br />
<br />
https://prof.ti.bfh.ch/hew1/informatik3/prolog/p-99/p92a.gif<br />
<br />
Anyway the puzzle goes like this: Given a tree with N nodes (and hence N-1 edges). Find a way to enumerate the nodes from 1 to N and, accordingly, the edges from 1 to N-1 in such a way, that for each edge K the difference of its node numbers equals to K. The conjecture is that this is always possible.<br />
<br />
For small trees the problem is easy to solve by hand. However, for larger trees, and 14 is already very large, it is extremely difficult to find a solution. And remember, we don't know for sure whether there is always a solution!<br />
<br />
Write a predicate that calculates a numbering scheme for a given tree. What is the solution for the larger tree pictured below?<br />
<br />
https://prof.ti.bfh.ch/hew1/informatik3/prolog/p-99/p92b.gif<br />
<br />
Example in Haskell:<br />
<br />
<haskell><br />
λ> head $ vonKoch [(1,6),(2,6),(3,6),(4,6),(5,6),(5,7),(5,8),(8,9),(5,10),(10,11),(11,12),(11,13),(13,14)]<br />
[6,7,8,9,3,4,10,11,5,12,2,13,14,1]<br />
</haskell><br />
<br />
[[99 questions/Solutions/92 | Solutions]]<br />
<br />
<br />
== Problem 93 ==<br />
<br />
(***) An arithmetic puzzle<br />
<br />
Given a list of integer numbers, find a correct way of inserting arithmetic signs (operators) such that the result is a correct equation. Example: With the list of numbers [2,3,5,7,11] we can form the equations 2-3+5+7 = 11 or 2 = (3*5+7)/11 (and ten others!).<br />
<br />
Division should be interpreted as operating on rationals, and division by zero should be avoided.<br />
<br />
Example in Haskell:<br />
<br />
<haskell><br />
λ> mapM_ putStrLn $ puzzle [2,3,5,7,11]<br />
2 = 3-(5+7-11)<br />
2 = 3-5-(7-11)<br />
2 = 3-(5+7)+11<br />
2 = 3-5-7+11<br />
2 = (3*5+7)/11<br />
2*(3-5) = 7-11<br />
2-(3-(5+7)) = 11<br />
2-(3-5-7) = 11<br />
2-(3-5)+7 = 11<br />
2-3+5+7 = 11<br />
</haskell><br />
<br />
The other two solutions alluded to in the problem description are dropped by the Haskell solution as trivial variants:<br />
<br />
<pre><br />
2 = 3-(5+(7-11))<br />
2-3+(5+7) = 11<br />
</pre><br />
<br />
[[99 questions/Solutions/93 | Solutions]]<br />
<br />
<br />
== Problem 94 ==<br />
<br />
(***) Generate K-regular simple graphs with N nodes<br />
<br />
In a K-regular graph all nodes have a degree of K; i.e. the number of edges incident in each node is K. How many (non-isomorphic!) 3-regular graphs with 6 nodes are there?<br />
<br />
[https://prof.ti.bfh.ch/hew1/informatik3/prolog/p-99/p94.txt Sample results]<br />
<br />
Example in Haskell:<br />
<haskell><br />
λ> length $ regular 6 3<br />
2<br />
</haskell><br />
<br />
[[99 questions/Solutions/94 | Solutions]]<br />
<br />
[[Category:Tutorials]]</div>Wizzuphttps://wiki.haskell.org/index.php?title=99_questions/90_to_94&diff=6277799 questions/90 to 942019-02-16T07:30:45Z<p>Wizzup: unify ghci prompts</p>
<hr />
<div>__NOTOC__<br />
<br />
This is part of [[H-99:_Ninety-Nine_Haskell_Problems|Ninety-Nine Haskell Problems]], based on [https://prof.ti.bfh.ch/hew1/informatik3/prolog/p-99/ Ninety-Nine Prolog Problems].<br />
<br />
If you want to work on one of these, put your name in the block so we know someone's working on it. Then, change n in your block to the appropriate problem number, and fill in the <Problem description>,<example in Haskell>,<solution in haskell> and <description of implementation> fields. <br />
<br />
== Problem 90 ==<br />
<br />
(**) Eight queens problem<br />
<br />
This is a classical problem in computer science. The objective is to place eight queens on a chessboard so that no two queens are attacking each other; i.e., no two queens are in the same row, the same column, or on the same diagonal.<br />
<br />
Hint: Represent the positions of the queens as a list of numbers 1..N. Example: [4,2,7,3,6,8,5,1] means that the queen in the first column is in row 4, the queen in the second column is in row 2, etc. Use the generate-and-test paradigm.<br />
<br />
Example in Haskell:<br />
<br />
<haskell><br />
λ> length (queens 8)<br />
92<br />
λ> head (queens 8)<br />
[1,5,8,6,3,7,2,4]<br />
</haskell><br />
<br />
[[99 questions/Solutions/90 | Solutions]]<br />
<br />
<br />
== Problem 91 ==<br />
<br />
(**) Knight's tour<br />
<br />
Another famous problem is this one: How can a knight jump on an NxN chessboard in such a way that it visits every square exactly once? A set of solutions is given on the [[The_Knights_Tour]] page.<br />
<br />
Hints: Represent the squares by pairs of their coordinates of the form X/Y, where both X and Y are integers between 1 and N. (Note that '/' is just a convenient functor, not division!) Define the relation jump(N,X/Y,U/V) to express the fact that a knight can jump from X/Y to U/V on a NxN chessboard. And finally, represent the solution of our problem as a list of N*N knight positions (the knight's tour).<br />
<br />
There are two variants of this problem:<br />
# find a tour ending at a particular square<br />
# find a circular tour, ending a knight's jump from the start (clearly it doesn't matter where you start, so choose (1,1))<br />
<br />
Example in Haskell:<br />
<br />
<haskell><br />
λ> head $ knightsTo 8 (1,1)<br />
[(2,7),(3,5),(5,6),(4,8),(3,6),(4,4),(6,5),(4,6),<br />
(5,4),(7,5),(6,3),(5,5),(4,3),(2,4),(1,6),(2,8),<br />
(4,7),(6,8),(8,7),(6,6),(4,5),(6,4),(5,2),(7,1),<br />
(8,3),(6,2),(8,1),(7,3),(8,5),(7,7),(5,8),(3,7),<br />
(1,8),(2,6),(3,4),(1,5),(2,3),(3,1),(1,2),(3,3),<br />
(1,4),(2,2),(4,1),(5,3),(7,4),(8,2),(6,1),(4,2),<br />
(2,1),(1,3),(2,5),(1,7),(3,8),(5,7),(7,8),(8,6),<br />
(6,7),(8,8),(7,6),(8,4),(7,2),(5,1),(3,2),(1,1)]<br />
λ> head $ closedKnights 8 <br />
[(1,1),(3,2),(1,3),(2,1),(3,3),(5,4),(6,6),(4,5),<br />
(2,6),(1,8),(3,7),(5,8),(4,6),(2,5),(4,4),(5,6),<br />
(6,4),(8,5),(7,7),(6,5),(5,3),(6,1),(4,2),(6,3),<br />
(8,2),(7,4),(5,5),(3,4),(1,5),(2,7),(4,8),(3,6),<br />
(1,7),(3,8),(5,7),(7,8),(8,6),(6,7),(8,8),(7,6),<br />
(8,4),(7,2),(5,1),(4,3),(3,5),(1,4),(2,2),(4,1),<br />
(6,2),(8,1),(7,3),(5,2),(7,1),(8,3),(7,5),(8,7),<br />
(6,8),(4,7),(2,8),(1,6),(2,4),(1,2),(3,1),(2,3)]<br />
</haskell><br />
<br />
[[99 questions/Solutions/91 | Solutions]]<br />
<br />
<br />
== Problem 92 ==<br />
<br />
(***) Von Koch's conjecture<br />
<br />
Several years ago I met a mathematician who was intrigued by a problem for which he didn't know a solution. His name was Von Koch, and I don't know whether the problem has been solved since.<br />
<br />
https://prof.ti.bfh.ch/hew1/informatik3/prolog/p-99/p92a.gif<br />
<br />
Anyway the puzzle goes like this: Given a tree with N nodes (and hence N-1 edges). Find a way to enumerate the nodes from 1 to N and, accordingly, the edges from 1 to N-1 in such a way, that for each edge K the difference of its node numbers equals to K. The conjecture is that this is always possible.<br />
<br />
For small trees the problem is easy to solve by hand. However, for larger trees, and 14 is already very large, it is extremely difficult to find a solution. And remember, we don't know for sure whether there is always a solution!<br />
<br />
Write a predicate that calculates a numbering scheme for a given tree. What is the solution for the larger tree pictured below?<br />
<br />
https://prof.ti.bfh.ch/hew1/informatik3/prolog/p-99/p92b.gif<br />
<br />
Example in Haskell:<br />
<br />
<haskell><br />
λ> head $ vonKoch [(1,6),(2,6),(3,6),(4,6),(5,6),(5,7),(5,8),(8,9),(5,10),(10,11),(11,12),(11,13),(13,14)]<br />
[6,7,8,9,3,4,10,11,5,12,2,13,14,1]<br />
</haskell><br />
<br />
[[99 questions/Solutions/92 | Solutions]]<br />
<br />
<br />
== Problem 93 ==<br />
<br />
(***) An arithmetic puzzle<br />
<br />
Given a list of integer numbers, find a correct way of inserting arithmetic signs (operators) such that the result is a correct equation. Example: With the list of numbers [2,3,5,7,11] we can form the equations 2-3+5+7 = 11 or 2 = (3*5+7)/11 (and ten others!).<br />
<br />
Division should be interpreted as operating on rationals, and division by zero should be avoided.<br />
<br />
Example in Haskell:<br />
<br />
<haskell><br />
λ> mapM_ putStrLn $ puzzle [2,3,5,7,11]<br />
2 = 3-(5+7-11)<br />
2 = 3-5-(7-11)<br />
2 = 3-(5+7)+11<br />
2 = 3-5-7+11<br />
2 = (3*5+7)/11<br />
2*(3-5) = 7-11<br />
2-(3-(5+7)) = 11<br />
2-(3-5-7) = 11<br />
2-(3-5)+7 = 11<br />
2-3+5+7 = 11<br />
</haskell><br />
<br />
The other two solutions alluded to in the problem description are dropped by the Haskell solution as trivial variants:<br />
<br />
<pre><br />
2 = 3-(5+(7-11))<br />
2-3+(5+7) = 11<br />
</pre><br />
<br />
[[99 questions/Solutions/93 | Solutions]]<br />
<br />
<br />
== Problem 94 ==<br />
<br />
(***) Generate K-regular simple graphs with N nodes<br />
<br />
In a K-regular graph all nodes have a degree of K; i.e. the number of edges incident in each node is K. How many (non-isomorphic!) 3-regular graphs with 6 nodes are there?<br />
<br />
[https://prof.ti.bfh.ch/hew1/informatik3/prolog/p-99/p94.txt Sample results]<br />
<br />
Example in Haskell:<br />
<haskell><br />
λ> length $ regular 6 3<br />
2<br />
</haskell><br />
<br />
[[99 questions/Solutions/94 | Solutions]]<br />
<br />
[[Category:Tutorials]]</div>Wizzuphttps://wiki.haskell.org/index.php?title=99_questions/80_to_89&diff=6277699 questions/80 to 892019-02-16T07:26:58Z<p>Wizzup: unify ghci prompts</p>
<hr />
<div>__NOTOC__<br />
<br />
This is part of [[H-99:_Ninety-Nine_Haskell_Problems|Ninety-Nine Haskell Problems]], based on [https://prof.ti.bfh.ch/hew1/informatik3/prolog/p-99/ Ninety-Nine Prolog Problems].<br />
<br />
If you want to work on one of these, put your name in the block so we know someone's working on it. Then, change n in your block to the appropriate problem number, and fill in the <Problem description>,<example in lisp>,<example in Haskell>,<solution in haskell> and <description of implementation> fields. <br />
<br />
== Graphs ==<br />
<br />
A graph is defined as a set of nodes and a set of edges, where each edge is a pair of nodes. <br />
<br />
https://prof.ti.bfh.ch/hew1/informatik3/prolog/p-99/graph1.gif<br />
<br />
There are several ways to represent graphs in Prolog. One method is to represent each edge separately as one clause (fact). In this form, the graph depicted below is represented as the following predicate: <br />
<br />
edge(h,g).<br />
edge(k,f).<br />
edge(f,b).<br />
...<br />
<br />
We call this ''edge-clause'' form. Obviously, isolated nodes cannot be represented. Another method is to represent the whole graph as one data object. According to the definition of the graph as a pair of two sets (nodes and edges), we may use the following Prolog term to represent the example graph:<br />
<br />
graph([b,c,d,f,g,h,k],[e(b,c),e(b,f),e(c,f),e(f,k),e(g,h)])<br />
<br />
We call this ''graph-term'' form. Note, that the lists are kept sorted, they are really ''sets'', without duplicated elements. Each edge appears only once in the edge list; i.e. an edge from a node x to another node y is represented as e(x,y), the term e(y,x) is not present. '''The graph-term form is our default representation.''' In SWI-Prolog there are predefined predicates to work with sets. <br />
<br />
A third representation method is to associate with each node the set of nodes that are adjacent to that node. We call this the ''adjacency-list'' form. In our example:<br />
<br />
[n(b,[c,f]), n(c,[b,f]), n(d,[]), n(f,[b,c,k]), ...]<br />
<br />
The representations we introduced so far are Prolog terms and therefore well suited for automated processing, but their syntax is not very user-friendly. Typing the terms by hand is cumbersome and error-prone. We can define a more compact and "human-friendly" notation as follows: A graph is represented by a list of atoms and terms of the type X-Y (i.e. functor '-' and arity 2). The atoms stand for isolated nodes, the X-Y terms describe edges. If an X appears as an endpoint of an edge, it is automatically defined as a node. Our example could be written as:<br />
<br />
[b-c, f-c, g-h, d, f-b, k-f, h-g]<br />
<br />
We call this the ''human-friendly'' form. As the example shows, the list does not have to be sorted and may even contain the same edge multiple times. Notice the isolated node d. (Actually, isolated nodes do not even have to be atoms in the Prolog sense, they can be compound terms, as in <tt>d(3.75,blue)</tt> instead of <tt>d</tt> in the example). <br />
<br />
https://prof.ti.bfh.ch/hew1/informatik3/prolog/p-99/graph2.gif<br />
<br />
When the edges are directed we call them arcs. These are represented by ordered pairs. Such a graph is called '''directed graph'''. To represent a directed graph, the forms discussed above are slightly modified. The example graph above is represented as follows: <br />
<br />
''Arc-clause form''<br />
<br />
arc(s,u).<br />
arc(u,r).<br />
...<br />
<br />
''Graph-term form''<br />
<br />
digraph([r,s,t,u,v],[a(s,r),a(s,u),a(u,r),a(u,s),a(v,u)])<br />
<br />
''Adjacency-list form''<br />
<br />
[n(r,[]),n(s,[r,u]),n(t,[]),n(u,[r]),n(v,[u])]<br />
<br />
Note that the adjacency-list does not have the information on whether it is a graph or a digraph.<br />
<br />
''Human-friendly form''<br />
<br />
[s > r, t, u > r, s > u, u > s, v > u] <br />
<br />
Finally, graphs and digraphs may have additional information attached to nodes and edges (arcs). For the nodes, this is no problem, as we can easily replace the single character identifiers with arbitrary compound terms, such as <tt>city('London',4711)</tt>. On the other hand, for edges we have to extend our notation. Graphs with additional information attached to edges are called '''labelled graphs'''.<br />
<br />
https://prof.ti.bfh.ch/hew1/informatik3/prolog/p-99/graph3.gif<br />
<br />
''Arc-clause form''<br />
<br />
arc(m,q,7).<br />
arc(p,q,9).<br />
arc(p,m,5).<br />
<br />
''Graph-term form''<br />
<br />
digraph([k,m,p,q],[a(m,p,7),a(p,m,5),a(p,q,9)])<br />
<br />
''Adjacency-list form''<br />
<br />
[n(k,[]),n(m,[q/7]),n(p,[m/5,q/9]),n(q,[])]<br />
<br />
Notice how the edge information has been packed into a term with functor '/' and arity 2, together with the corresponding node.<br />
<br />
''Human-friendly form''<br />
<br />
[p>q/9, m>q/7, k, p>m/5]<br />
<br />
The notation for labelled graphs can also be used for so-called '''multi-graphs''', where more than one edge (or arc) are allowed between two given nodes.<br />
<br />
== Problem 80 ==<br />
<br />
(***) Conversions<br />
<br />
Write predicates to convert between the different graph representations. With these predicates, all representations are equivalent; i.e. for the following problems you can always pick freely the most convenient form. The reason this problem is rated (***) is not because it's particularly difficult, but because it's a lot of work to deal with all the special cases.<br />
<br />
Example in Haskell:<br />
<br />
<haskell><br />
λ> graphToAdj Graph ['b','c','d','f','g','h','k'] [('b','c'),('b','f'),('c','f'),('f','k'),('g','h')]<br />
Adj [('b', "cf"), ('c', "bf"), ('d', ""), ('f', "bck"), ('g', "h"), ('h', "g"), ('k', "f")]<br />
</haskell><br />
<br />
[[99 questions/Solutions/80 | Solutions ]]<br />
<br />
== Problem 81 ==<br />
<br />
(**) Path from one node to another one<br />
<br />
Write a function that, given two nodes a and b in a graph, returns all the acyclic paths from a to b.<br />
<br />
Example in Haskell:<br />
<br />
<haskell><br />
λ> paths 1 4 [(1,2),(2,3),(1,3),(3,4),(4,2),(5,6)]<br />
[[1,2,3,4],[1,3,4]]<br />
λ> paths 2 6 [(1,2),(2,3),(1,3),(3,4),(4,2),(5,6)]<br />
[]<br />
</haskell><br />
[[99 questions/Solutions/81 | Solutions ]]<br />
<br />
== Problem 82 ==<br />
<br />
(*) Cycle from a given node<br />
<br />
Write a predicate cycle(G,A,P) to find a closed path (cycle) P starting at a given node A in the graph G. The predicate should return all cycles via backtracking.<br />
<br />
Example in Haskell:<br />
<br />
<haskell><br />
λ> cycle 2 [(1,2),(2,3),(1,3),(3,4),(4,2),(5,6)]<br />
[[2,3,4,2]]<br />
λ> cycle 1 [(1,2),(2,3),(1,3),(3,4),(4,2),(5,6)]<br />
[]<br />
</haskell><br />
<br />
[[99 questions/Solutions/82 | Solutions ]]<br />
<br />
== Problem 83 ==<br />
<br />
(**) Construct all spanning trees <br />
<br />
Write a predicate s_tree(Graph,Tree) to construct (by backtracking) all spanning trees of a given graph. With this predicate, find out how many spanning trees there are for the graph depicted to the left. The data of this example graph can be found in the file p83.dat. When you have a correct solution for the s_tree/2 predicate, use it to define two other useful predicates: is_tree(Graph) and is_connected(Graph). Both are five-minutes tasks!<br />
<br />
Example in Haskell:<br />
<br />
<haskell><br />
λ> length $ spanningTree k4<br />
16<br />
</haskell><br />
<br />
[[99 questions/Solutions/83 | Solutions ]]<br />
<br />
== Problem 84 ==<br />
<br />
(**) Construct the minimal spanning tree<br />
<br />
Write a predicate ms_tree(Graph,Tree,Sum) to construct the minimal spanning tree of a given labelled graph. Hint: Use the algorithm of Prim. A small modification of the solution of P83 does the trick. The data of the example graph to the right can be found in the file p84.dat.<br />
<br />
Example in Haskell:<br />
<br />
<haskell><br />
λ> prim [1,2,3,4,5] [(1,2,12),(1,3,34),(1,5,78),(2,4,55),(2,5,32),(3,4,61),(3,5,44),(4,5,93)]<br />
[(1,2,12),(1,3,34),(2,4,55),(2,5,32)]<br />
</haskell><br />
<br />
[[99 questions/Solutions/84 | Solutions ]]<br />
<br />
<br />
== Problem 85 ==<br />
<br />
(**) Graph isomorphism<br />
<br />
Two graphs G1(N1,E1) and G2(N2,E2) are isomorphic if there is a bijection f: N1 -> N2 such that for any nodes X,Y of N1, X and Y are adjacent if and only if f(X) and f(Y) are adjacent.<br />
<br />
Write a predicate that determines whether two graphs are isomorphic. Hint: Use an open-ended list to represent the function f.<br />
<br />
Example in Haskell:<br />
<br />
<haskell><br />
λ> graphG1 = [1,2,3,4,5,6,7,8] [(1,5),(1,6),(1,7),(2,5),(2,6),(2,8),(3,5),(3,7),(3,8),(4,6),(4,7),(4,8)]<br />
λ> graphH1 = [1,2,3,4,5,6,7,8] [(1,2),(1,4),(1,5),(6,2),(6,5),(6,7),(8,4),(8,5),(8,7),(3,2),(3,4),(3,7)]<br />
λ> iso graphG1 graphH1<br />
True<br />
</haskell><br />
<br />
[[99 questions/Solutions/85 | Solutions ]]<br />
<br />
== Problem 86 ==<br />
<br />
(**) Node degree and graph coloration<br />
<br />
a) Write a predicate degree(Graph,Node,Deg) that determines the degree of a given node.<br />
<br />
b) Write a predicate that generates a list of all nodes of a graph sorted according to decreasing degree.<br />
<br />
c) Use Welch-Powell's algorithm to paint the nodes of a graph in such a way that adjacent nodes have different colors.<br />
<br />
Example in Haskell:<br />
<br />
<haskell><br />
λ> kColor ['a','b','c','d','e','f','g','h','i','j'] [('a','b'),('a','e'),('a','f'),('b','c'),('b','g'),('c','d'),('c','h'),('d','e'),('d','i'),('e','j'),('f','h'),('f','i'),('g','i'),('g','j'),('h','j')]<br />
[('a',1),('b',2),('c',1),('d',2),('e',3),('f',2),('g',1),('h',3),('i',3),('j',2)]<br />
</haskell><br />
<br />
[[99 questions/Solutions/86 | Solutions ]]<br />
<br />
== Problem 87 ==<br />
<br />
(**) Depth-first order graph traversal (alternative solution)<br />
<br />
Write a predicate that generates a depth-first order graph traversal sequence. The starting point should be specified, and the output should be a list of nodes that are reachable from this starting point (in depth-first order).<br />
<br />
Example in Haskell:<br />
<br />
<haskell><br />
λ> depthFirst ([1,2,3,4,5,6,7], [(1,2),(2,3),(1,4),(3,4),(5,2),(5,4),(6,7)]) 1<br />
[1,2,3,4,5]<br />
</haskell><br />
<br />
[[99 questions/Solutions/87 | Solutions ]]<br />
<br />
== Problem 88 ==<br />
<br />
(**) Connected components (alternative solution)<br />
<br />
Write a predicate that splits a graph into its connected components.<br />
<br />
Example in Haskell:<br />
<br />
<haskell><br />
λ> connectedComponents ([1,2,3,4,5,6,7], [(1,2),(2,3),(1,4),(3,4),(5,2),(5,4),(6,7)])<br />
[[1,2,3,4,5][6,7]]<br />
</haskell><br />
<br />
[[99 questions/Solutions/88 | Solutions ]]<br />
<br />
== Problem 89 ==<br />
<br />
(**) Bipartite graphs<br />
<br />
Write a predicate that finds out whether a given graph is bipartite.<br />
<br />
Example in Haskell:<br />
<br />
<haskell><br />
λ> bipartite ([1,2,3,4,5],[(1,2),(2,3),(1,4),(3,4),(5,2),(5,4)])<br />
True<br />
λ> bipartite ([1,2,3,4,5],[(1,2),(2,3),(1,4),(3,4),(5,2),(5,4),(1,3)])<br />
False<br />
</haskell><br />
<br />
[[99 questions/Solutions/89 | Solutions ]]<br />
<br />
<br />
[[Category:Tutorials]]</div>Wizzuphttps://wiki.haskell.org/index.php?title=BayHac&diff=62773BayHac2019-02-13T11:30:23Z<p>Wizzup: </p>
<hr />
<div>See the following pages for Haskell Hackathons in the San Francisco Bay Area & Silicon Valley:<br />
<br />
* [[BayHac2011]]<br />
* [[BayHac2012]]<br />
* [[BayHac2013]]<br />
* [[BayHac2014]]<br />
* [[BayHac2015]]<br />
* [[BayHac2017]]<br />
* [[BayHac2018]]<br />
* [[BayHac2019]] <- Next BayHac: TBD, 2019<br />
<br />
<br />
[[Category:Community]]</div>Wizzuphttps://wiki.haskell.org/index.php?title=Talk:BayHac2014/Prolog&diff=62772Talk:BayHac2014/Prolog2019-02-13T11:27:41Z<p>Wizzup: Created page with "== Slide == I can't find slide anywhere on the net. ~~~~"</p>
<hr />
<div>== Slide ==<br />
I can't find slide anywhere on the net. [[User:Wizzup|Wizzup]] ([[User talk:Wizzup|talk]]) 11:27, 13 February 2019 (UTC)</div>Wizzuphttps://wiki.haskell.org/index.php?title=BayHac2014/Prolog&diff=62771BayHac2014/Prolog2019-02-13T11:26:34Z<p>Wizzup: Add link to youtube videos</p>
<hr />
<div>== From Prolog to Hindley Milner ==<br />
<br />
In this talk, I introduced logic programming with Prolog, went over how to implement unification in Haskell and talked about how type inference and typeclasses can be thought of in terms of logic programming.<br />
<br />
Here's the code for the whole unification function; you can probably remember each individual part from the talk.<br />
<haskell><br />
unify :: Predicate -> Predicate -> Maybe MGU<br />
unify (Predicate _ name1 body1) (Predicate _ name2 body2)<br />
| name1 /= name2 || length body1 /= length body2 = Nothing<br />
| otherwise = foldM combine [] $ zip body1 body2<br />
where combine mgu (left, right) = go mgu (subst mgu left) (subst mgu right)<br />
go mgu (Var l) r | not (r `contains` Var l) = Just $ (l, r) : mgu<br />
go mgu l (Var r) | not (l `contains` Var r) = Just $ (r, l) : mgu<br />
go mgu (Pred l) (Pred r) = merge <$> unify l r <*> Just mgu<br />
go mgu l r = if l == r then Just mgu else Nothing<br />
</haskell><br />
<br />
<br />
The only part I didn't actually cover is <hask>combine</hask>. This is just a little helper function that takes the two terms I'm unifying, updates them with the MGU so far and calls the actual case-by-case part of the unification algorithm on the resulting terms.<br />
<br />
You can see the entire code (although without comments) on [https://github.com/TikhonJelvis/Simple-Prolog/tree/master/src/Prolog/Interpreter.hs GitHub]. I also included a few demo prolog (.pl) files you can play with, either by running my interpreter or using a real one like swipl. These files contain most of the Prolog code from my talk and some comments to help explain what's going on and give you a few exercises to better understand logic programming.<br />
<br />
Right now, the slides themselves are a little broken, so I'm not putting them up yet.<br />
<br />
I've also been thinking about doing this talk again, maybe at one of the Haskell meetups. So if you're interested but missed it—or, for whatever reason, want to see it again :)—you'll probably have a chance. I'll also try to improve it based on feedback I've gotten; if you have anything to say, please email me at tikhon@jelv.is. (I ''especially'' appreciate criticism and hearing about what you found confusing or poorly explained!)<br />
<br />
== Video records ==<br />
<br />
There are four parts video on youtube available: <br />
[https://www.youtube.com/watch?v=qo6NgTZ0bSk 1],<br />
[https://www.youtube.com/watch?v=A5Gm_u_0WD8 2],<br />
[https://www.youtube.com/watch?v=BSykkPjJ4tI 3],<br />
[https://www.youtube.com/watch?v=BDJgyzTuEWw 4]</div>Wizzuphttps://wiki.haskell.org/index.php?title=Talk:GraphParserCombinators&diff=62769Talk:GraphParserCombinators2019-02-13T02:12:52Z<p>Wizzup: /* Link to paper is dead */</p>
<hr />
<div>== Link to paper is dead ==<br />
<br />
I think the published versions are one of followings (paywall)<br />
<br />
https://doi.org/10.1007/978-3-540-70590-1_18<br />
<br />
https://doi.org/10.1007/978-3-540-85373-2_1<br />
<br />
[[User:Wizzup|Wizzup]] ([[User talk:Wizzup|talk]]) 02:12, 13 February 2019 (UTC)</div>Wizzuphttps://wiki.haskell.org/index.php?title=Talk:GraphParserCombinators&diff=62768Talk:GraphParserCombinators2019-02-13T02:12:26Z<p>Wizzup: </p>
<hr />
<div>== Link to paper is dead ==<br />
<br />
I think the published versions are one of followings (paywall)<br />
<br />
https://doi.org/10.1007/978-3-540-70590-1_18<br />
https://doi.org/10.1007/978-3-540-85373-2_1<br />
<br />
[[User:Wizzup|Wizzup]] ([[User talk:Wizzup|talk]]) 02:12, 13 February 2019 (UTC)</div>Wizzuphttps://wiki.haskell.org/index.php?title=Talk:GraphParserCombinators&diff=62767Talk:GraphParserCombinators2019-02-13T02:12:12Z<p>Wizzup: Created page with "== Link to paper is dead. I think the published versions are one of followings (paywall) https://doi.org/10.1007/978-3-540-70590-1_18 https://doi.org/10.1007/978-3-540-85373..."</p>
<hr />
<div>== Link to paper is dead.<br />
<br />
I think the published versions are one of followings (paywall)<br />
<br />
https://doi.org/10.1007/978-3-540-70590-1_18<br />
https://doi.org/10.1007/978-3-540-85373-2_1<br />
<br />
[[User:Wizzup|Wizzup]] ([[User talk:Wizzup|talk]]) 02:12, 13 February 2019 (UTC)</div>Wizzuphttps://wiki.haskell.org/index.php?title=Euler_problems&diff=62766Euler problems2019-02-13T01:17:47Z<p>Wizzup: </p>
<hr />
<div>These are solutions to the problems listed on [http://projecteuler.net/index.php?section=view Project Euler].<br />
<br />
'''WARNING''' - Do not peek at any of these pages if you want to enjoy the<br />
benefits of Project Euler, unless you have already solved the problems.<br />
<br />
The existence of these pages is very controversial; see the [[Talk:Euler problems|talk page]] for discussion. Many P.E. participants regard it as a global Internet competition which is being compromised by these readily available solutions, and some other sites hide their solution methods so that only those who know the answer can view them. The FAQ on the [http://www.projecteuler.net/ front page of the Project Euler site] says the following, which appears to be a reference to pages such as this one:<br />
<br />
<blockquote><br />
<p><em>I solved it by using a search engine, does that matter?</em></p><br />
<p>That depends on your motivation for solving the problems. It probably means that you've missed out on some beautiful and hidden mathematics.</p><br />
</blockquote><br />
<br />
In any case, it is recommended that you try the problems yourself before looking<br />
at the solutions. These are great exercises for improving your Haskell-fu, and reading the solutions beforehand could spoil the experience of solving them yourself.<br />
<br />
Any further reading is at your own risk.<br />
<br />
* [[Euler problems/1 to 10|Questions 1 to 10]]<br />
* [[Euler problems/11 to 20|Questions 11 to 20]]<br />
* [[Euler problems/21 to 30|Questions 21 to 30]]<br />
* [[Euler problems/31 to 40|Questions 31 to 40]]<br />
* [[Euler problems/41 to 50|Questions 41 to 50]]<br />
* [[Euler problems/51 to 60|Questions 51 to 60]]<br />
* [[Euler problems/61 to 70|Questions 61 to 70]]<br />
* [[Euler problems/71 to 80|Questions 71 to 80]]<br />
* [[Euler problems/81 to 90|Questions 81 to 90]]<br />
* [[Euler problems/91 to 100|Questions 91 to 100]]<br />
* [[Euler problems/101 to 110|Questions 101 to 110]]<br />
* [[Euler problems/111 to 120|Questions 111 to 120]]<br />
* [[Euler problems/121 to 130|Questions 121 to 130]]<br />
* [[Euler problems/131 to 140|Questions 131 to 140]]<br />
* [[Euler problems/141 to 150|Questions 141 to 150]]<br />
* [[Euler problems/151 to 160|Questions 151 to 160]]<br />
* [[Euler problems/161 to 170|Questions 161 to 170]]<br />
* [[Euler problems/171 to 180|Questions 171 to 180]]<br />
* [[Euler problems/181 to 190|Questions 181 to 190]]<br />
* [[Euler problems/191 to 200|Questions 191 to 200]]<br />
<br />
[[Category:Tutorials]]<br />
[[Category:Code]]<br />
[[Category:Programming exercise spoilers]]</div>Wizzuphttps://wiki.haskell.org/index.php?title=Common_Language_Runtime&diff=62763Common Language Runtime2019-02-09T10:31:28Z<p>Wizzup: </p>
<hr />
<div>[[Category:CLR]]<br />
'''Question:'''<br />
<br />
Can I use Haskell with the Common Language Runtime (CLR). In other words .Net / Mono / CoreCLR?<br />
<br />
'''Answer:'''<br />
<br />
If you're looking for a way to run Haskell on (aka target) the CLR, then the short answer is you can't.<br />
<br />
A resonable approach to hacking this up you're selves might be to work on GHC backend that outputs common intermediate language (aka MSIL), and perhaps via the LLVM backend? The GCH JS crew have made some good progress on creating a new target for GHC so it's doable at least.<br />
<br />
If you're instead looking for a way to bridge between the Haskell & CLR eco systems, then reality for you isn't quite as grim.<br />
<br />
There was the pragmatic [https://hackage.haskell.org/package/hs-dotnet hs-dotnet] package. This might be considered dead by now, though experiment as you please and update the wiki with your results.<br />
<br />
Another, not so dead alternative is [[Salsa]]. A common misconception is that:<br />
[https://www.reddit.com/r/haskell/comments/xsfqg/why_isnt_there_a_net_implementation_of_haskell/c5p8tip ''"Haskell's type system has no way to represent inheritance, overloading or method calls"'']. This is false (if for practical reasons we consider GHC = Haskell), and Salsa is library that has proven that these can indeed be encoded with the current state of GHC's type features.<br />
<br />
While Salsa is not quite dead, it also doesn't have an automated build system, and the copy on Hackage doesn't get updated. To give this spin, head over to github page, and follow the READMEs carefully. It it also the only Mono compatible solution (but again, may require manual steps - you'll likely need to pass in an "--extra-include-dirs=" param)<br />
<br />
'''Future directions?'''<br />
<br />
[https://www.reddit.com/r/haskell/comments/37d5xh/286_microsoft_users_windows_and_net_express_their/ Surveys have shown] that many people consider CLR support important or crucial for Haskell, but as far as I know few people are working on this.<br />
<br />
I for one, am actually making a CLR <-> Haskell bridge the primary project of my free time, but my free time is rather limited. It would be great if others could help out in this space, by either contributing to Salsa, or my new 'clr-haskell' project (very early work in progress):<br />
<br />
* [https://github.com/tim-m89/Salsa https://github.com/tim-m89/Salsa]<br />
* [https://gitlab.com/tim-m89/clr-haskell https://gitlab.com/tim-m89/clr-haskell]<br />
<br />
= See also =<br />
<br />
* [[Implementations]]</div>Wizzuphttps://wiki.haskell.org/index.php?title=99_questions/61_to_69&diff=6276299 questions/61 to 692019-02-09T09:51:02Z<p>Wizzup: unify ghci prompts</p>
<hr />
<div>__NOTOC__<br />
<br />
This is part of [[H-99:_Ninety-Nine_Haskell_Problems|Ninety-Nine Haskell Problems]], based on [https://prof.ti.bfh.ch/hew1/informatik3/prolog/p-99/ Ninety-Nine Prolog Problems].<br />
<br />
== Binary trees ==<br />
<br />
As defined in problem 54A.<br />
<br />
An example tree:<br />
<haskell><br />
tree4 = Branch 1 (Branch 2 Empty (Branch 4 Empty Empty))<br />
(Branch 2 Empty Empty)<br />
</haskell><br />
<br />
== Problem 61 ==<br />
<br />
Count the leaves of a binary tree<br />
<br />
A leaf is a node with no successors. Write a predicate count_leaves/2 to count them.<br />
<br />
Example:<br />
<br />
<pre><br />
% count_leaves(T,N) :- the binary tree T has N leaves<br />
</pre><br />
<br />
Example in Haskell:<br />
<br />
<haskell><br />
λ> countLeaves tree4<br />
2<br />
</haskell><br />
<br />
[[99 questions/Solutions/61 | Solutions]]<br />
<br />
== Problem 61A ==<br />
<br />
Collect the leaves of a binary tree in a list<br />
<br />
A leaf is a node with no successors. Write a predicate leaves/2 to collect them in a list.<br />
<br />
Example:<br />
<br />
<pre><br />
% leaves(T,S) :- S is the list of all leaves of the binary tree T<br />
</pre><br />
<br />
Example in Haskell:<br />
<br />
<haskell><br />
λ> leaves tree4<br />
[4,2]<br />
</haskell><br />
<br />
[[99 questions/Solutions/61A | Solutions]]<br />
<br />
== Problem 62 ==<br />
<br />
Collect the internal nodes of a binary tree in a list <br />
<br />
An internal node of a binary tree has either one or two non-empty successors. Write a predicate internals/2 to collect them in a list. <br />
<br />
Example:<br />
<br />
<pre><br />
% internals(T,S) :- S is the list of internal nodes of the binary tree T.<br />
</pre><br />
<br />
Example in Haskell:<br />
<br />
<haskell><br />
λ> internals tree4<br />
[1,2]<br />
</haskell><br />
<br />
[[99 questions/Solutions/62 | Solutions]]<br />
<br />
<br />
== Problem 62B ==<br />
<br />
Collect the nodes at a given level in a list<br />
<br />
A node of a binary tree is at level N if the path from the root to the node has length N-1. The root node is at level 1. Write a predicate atlevel/3 to collect all nodes at a given level in a list. <br />
<br />
Example:<br />
<br />
<pre><br />
% atlevel(T,L,S) :- S is the list of nodes of the binary tree T at level L<br />
</pre><br />
<br />
Example in Haskell:<br />
<br />
<haskell><br />
λ> atLevel tree4 2<br />
[2,2]<br />
</haskell><br />
<br />
[[99 questions/Solutions/62B | Solutions]]<br />
<br />
== Problem 63 ==<br />
<br />
Construct a complete binary tree<br />
<br />
A complete binary tree with height H is defined as follows:<br />
* The levels 1,2,3,...,H-1 contain the maximum number of nodes (i.e 2**(i-1) at the level i)<br />
* In level H, which may contain less than the maximum possible number of nodes, all the nodes are "left-adjusted". This means that in a levelorder tree traversal all internal nodes come first, the leaves come second, and empty successors (the nil's which are not really nodes!) come last. <br />
<br />
Particularly, complete binary trees are used as data structures (or addressing schemes) for heaps. <br />
<br />
We can assign an address number to each node in a complete binary tree by enumerating the nodes in level-order, starting at the root with number 1. For every node X with address A the following property holds: The address of X's left and right successors are 2*A and 2*A+1, respectively, if they exist. This fact can be used to elegantly construct a complete binary tree structure.<br />
<br />
Write a predicate complete_binary_tree/2.<br />
<br />
Example:<br />
<br />
<pre><br />
% complete_binary_tree(N,T) :- T is a complete binary tree with N nodes.<br />
</pre><br />
<br />
Example in Haskell:<br />
<br />
<haskell><br />
λ> completeBinaryTree 4<br />
Branch 'x' (Branch 'x' (Branch 'x' Empty Empty) Empty) (Branch 'x' Empty Empty)<br />
<br />
λ> isCompleteBinaryTree $ Branch 'x' (Branch 'x' Empty Empty) (Branch 'x' Empty Empty)<br />
True<br />
</haskell><br />
<br />
[[99 questions/Solutions/63 | Solutions]]<br />
<br />
== Problem 64 ==<br />
<br />
Given a binary tree as the usual Prolog term t(X,L,R) (or nil). As a preparation for drawing the tree, a layout algorithm is required to determine the position of each node in a rectangular grid. Several layout methods are conceivable, one of them is shown in the illustration below:<br />
<br />
https://prof.ti.bfh.ch/hew1/informatik3/prolog/p-99/p64.gif<br />
<br />
In this layout strategy, the position of a node v is obtained by the following two rules:<br />
* x(v) is equal to the position of the node v in the inorder sequence<br />
* y(v) is equal to the depth of the node v in the tree<br />
Write a function to annotate each node of the tree with a position, where (1,1) in the top left corner or the rectangle bounding the drawn tree.<br />
<br />
Here is the example tree from the above illustration:<br />
<br />
<haskell><br />
tree64 = Branch 'n'<br />
(Branch 'k'<br />
(Branch 'c'<br />
(Branch 'a' Empty Empty)<br />
(Branch 'h'<br />
(Branch 'g'<br />
(Branch 'e' Empty Empty)<br />
Empty<br />
)<br />
Empty<br />
)<br />
)<br />
(Branch 'm' Empty Empty)<br />
)<br />
(Branch 'u'<br />
(Branch 'p'<br />
Empty<br />
(Branch 's'<br />
(Branch 'q' Empty Empty)<br />
Empty<br />
)<br />
)<br />
Empty<br />
)<br />
</haskell><br />
<br />
Example in Haskell:<br />
<br />
<haskell><br />
λ> layout tree64<br />
Branch ('n',(8,1)) (Branch ('k',(6,2)) (Branch ('c',(2,3)) ...<br />
</haskell><br />
<br />
[[99 questions/Solutions/64 | Solutions]]<br />
<br />
<br />
== Problem 65 ==<br />
<br />
An alternative layout method is depicted in the illustration below:<br />
<br />
https://prof.ti.bfh.ch/hew1/informatik3/prolog/p-99/p65.gif<br />
<br />
Find out the rules and write the corresponding function.<br />
Hint: On a given level, the horizontal distance between neighboring nodes is constant.<br />
<br />
Use the same conventions as in problem P64 and test your function in an appropriate way.<br />
<br />
Here is the example tree from the above illustration:<br />
<br />
<haskell><br />
tree65 = Branch 'n'<br />
(Branch 'k'<br />
(Branch 'c'<br />
(Branch 'a' Empty Empty)<br />
(Branch 'e'<br />
(Branch 'd' Empty Empty)<br />
(Branch 'g' Empty Empty)<br />
)<br />
)<br />
(Branch 'm' Empty Empty)<br />
)<br />
(Branch 'u'<br />
(Branch 'p'<br />
Empty<br />
(Branch 'q' Empty Empty)<br />
)<br />
Empty<br />
)<br />
</haskell><br />
<br />
Example in Haskell:<br />
<br />
<haskell><br />
λ> layout tree65<br />
Branch ('n',(15,1)) (Branch ('k',(7,2)) (Branch ('c',(3,3)) ...<br />
</haskell><br />
<br />
[[99 questions/Solutions/65 | Solutions]]<br />
<br />
<br />
== Problem 66 ==<br />
<br />
Yet another layout strategy is shown in the illustration below:<br />
<br />
https://prof.ti.bfh.ch/hew1/informatik3/prolog/p-99/p66.gif<br />
<br />
The method yields a very compact layout while maintaining a certain symmetry in every node. Find out the rules and write the corresponding Prolog predicate. Hint: Consider the horizontal distance between a node and its successor nodes. How tight can you pack together two subtrees to construct the combined binary tree?<br />
<br />
Use the same conventions as in problem P64 and P65 and test your predicate in an appropriate way. Note: This is a difficult problem. Don't give up too early!<br />
<br />
Which layout do you like most?<br />
<br />
Example in Haskell:<br />
<br />
<haskell><br />
λ> layout tree65<br />
Branch ('n',(5,1)) (Branch ('k',(3,2)) (Branch ('c',(2,3)) ...<br />
</haskell><br />
<br />
[[99 questions/Solutions/66 | Solutions]]<br />
<br />
<br />
== Problem 67A ==<br />
<br />
A string representation of binary trees<br />
<br />
Somebody represents binary trees as strings of the following type:<br />
<br />
:a(b(d,e),c(,f(g,)))<br />
<br />
a) Write a Prolog predicate which generates this string representation, if the tree is given as usual (as nil or t(X,L,R) term). Then write a predicate which does this inverse; i.e. given the string representation, construct the tree in the usual form. Finally, combine the two predicates in a single predicate tree_string/2 which can be used in both directions.<br />
<br />
Example in Prolog<br />
<br />
<pre><br />
?- tree_to_string(t(x,t(y,nil,nil),t(a,nil,t(b,nil,nil))),S).<br />
S = 'x(y,a(,b))'<br />
?- string_to_tree('x(y,a(,b))',T).<br />
T = t(x, t(y, nil, nil), t(a, nil, t(b, nil, nil)))<br />
</pre><br />
<br />
Example in Haskell:<br />
<br />
<haskell><br />
λ> stringToTree "x(y,a(,b))" >>= print<br />
Branch 'x' (Branch 'y' Empty Empty) (Branch 'a' Empty (Branch 'b' Empty Empty))<br />
λ> let t = cbtFromList ['a'..'z'] in stringToTree (treeToString t) >>= print . (== t)<br />
True<br />
</haskell><br />
<br />
[[99 questions/Solutions/67A | Solutions]]<br />
<br />
<br />
== Problem 68 ==<br />
<br />
Preorder and inorder sequences of binary trees. We consider binary trees with nodes that are identified by single lower-case letters, as in the example of problem P67.<br />
<br />
a) Write predicates preorder/2 and inorder/2 that construct the preorder and inorder sequence of a given binary tree, respectively. The results should be atoms, e.g. 'abdecfg' for the preorder sequence of the example in problem P67.<br />
<br />
b) Can you use preorder/2 from problem part a) in the reverse direction; i.e. given a preorder sequence, construct a corresponding tree? If not, make the necessary arrangements.<br />
<br />
c) If both the preorder sequence and the inorder sequence of the nodes of a binary tree are given, then the tree is determined unambiguously. Write a predicate pre_in_tree/3 that does the job.<br />
<br />
Example in Haskell:<br />
<br />
<haskell><br />
λ> let { Just t = stringToTree "a(b(d,e),c(,f(g,)))" ;<br />
po = treeToPreorder t ;<br />
io = treeToInorder t } in preInTree po io >>= print<br />
Branch 'a' (Branch 'b' (Branch 'd' Empty Empty) (Branch 'e' Empty Empty)) (Branch 'c' Empty (Branch 'f' (Branch 'g' Empty Empty) Empty))<br />
</haskell><br />
<br />
[[99 questions/Solutions/68 | Solutions]]<br />
<br />
<br />
== Problem 69 ==<br />
<br />
Dotstring representation of binary trees.<br />
<br />
We consider again binary trees with nodes that are identified by single lower-case letters, as in the example of problem P67. Such a tree can be represented by the preorder sequence of its nodes in which dots (.) are inserted where an empty subtree (nil) is encountered during the tree traversal. For example, the tree shown in problem P67 is represented as 'abd..e..c.fg...'. First, try to establish a syntax (BNF or syntax diagrams) and then write a predicate tree_dotstring/2 which does the conversion in both directions. Use <br />
difference lists.<br />
<br />
Example in Haskell:<br />
<br />
<haskell><br />
λ> fst (ds2tree example)<br />
Branch 'a' (Branch 'b' (Branch 'd' Empty Empty) (Branch 'e' Empty Empty)) (Branch 'c' Empty (Branch 'f' (Branch 'g' Empty Empty) Empty))<br />
<br />
λ> tree2ds (Branch 'x' (Branch 'y' Empty Empty) (Branch 'z' (Branch '0' Empty Empty) Empty))<br />
"xy..z0..."<br />
</haskell><br />
<br />
[[99 questions/Solutions/69 | Solutions]]<br />
<br />
<br />
[[Category:Tutorials]]</div>Wizzuphttps://wiki.haskell.org/index.php?title=99_questions/70B_to_73&diff=6276199 questions/70B to 732019-02-09T09:37:55Z<p>Wizzup: unify ghci prompts</p>
<hr />
<div>__NOTOC__<br />
<br />
This is part of [[H-99:_Ninety-Nine_Haskell_Problems|Ninety-Nine Haskell Problems]], based on [https://prof.ti.bfh.ch/hew1/informatik3/prolog/p-99/ Ninety-Nine Prolog Problems].<br />
<br />
== Multiway Trees ==<br />
<br />
A multiway tree is composed of a root element and a (possibly empty) set of successors which are multiway trees themselves. A multiway tree is never empty. The set of successor trees is sometimes called a forest.<br />
<br />
https://prof.ti.bfh.ch/hew1/informatik3/prolog/p-99/p70.gif<br />
<br />
== Problem 70B ==<br />
<br />
(*) Check whether a given term represents a multiway tree.<br />
<br />
In Prolog or Lisp, one writes a predicate to check this.<br />
<br />
Example in Prolog:<br />
<br />
<pre><br />
?- istree(t(a,[t(f,[t(g,[])]),t(c,[]),t(b,[t(d,[]),t(e,[])])])).<br />
Yes<br />
</pre><br />
<br />
In Haskell, we define multiway trees as a datatype, as in the module [http://www.haskell.org/ghc/docs/latest/html/libraries/containers/Data-Tree.html Data.Tree]:<br />
<br />
<haskell><br />
data Tree a = Node a [Tree a]<br />
deriving (Eq, Show)<br />
</haskell><br />
<br />
Some example trees:<br />
<br />
<haskell><br />
tree1 = Node 'a' []<br />
<br />
tree2 = Node 'a' [Node 'b' []]<br />
<br />
tree3 = Node 'a' [Node 'b' [Node 'c' []]]<br />
<br />
tree4 = Node 'b' [Node 'd' [], Node 'e' []]<br />
<br />
tree5 = Node 'a' [<br />
Node 'f' [Node 'g' []],<br />
Node 'c' [],<br />
Node 'b' [Node 'd' [], Node 'e' []]<br />
]<br />
</haskell><br />
<br />
The last is the tree illustrated above.<br />
<br />
As in problem 54A, all members of this type are multiway trees; there is no use for a predicate to test them.<br />
<br />
== Problem 70C ==<br />
<br />
(*) Count the nodes of a multiway tree.<br />
<br />
Example in Haskell:<br />
<br />
<haskell><br />
λ> nnodes tree2<br />
2<br />
</haskell><br />
<br />
[[99 questions/Solutions/70C | Solutions]]<br />
<br />
== Problem 70 ==<br />
<br />
(**) Tree construction from a node string.<br />
<br />
We suppose that the nodes of a multiway tree contain single characters. In the depth-first order sequence of its nodes, a special character ^ has been inserted whenever, during the tree traversal, the move is a backtrack to the previous level.<br />
<br />
By this rule, the tree below (<tt>tree5</tt>) is represented as: <tt>afg^^c^bd^e^^^</tt><br />
<br />
https://prof.ti.bfh.ch/hew1/informatik3/prolog/p-99/p70.gif<br />
<br />
Define the syntax of the string and write a predicate tree(String,Tree) to construct the Tree when the String is given.<br />
Make your predicate work in both directions.<br />
<br />
Example in Haskell:<br />
<br />
<haskell><br />
λ> stringToTree "afg^^c^bd^e^^^"<br />
Node 'a' [Node 'f' [Node 'g' []],Node 'c' [],Node 'b' [Node 'd' [],Node 'e' []]]<br />
<br />
λ> treeToString (Node 'a' [Node 'f' [Node 'g' []],Node 'c' [],Node 'b' [Node 'd' [],Node 'e' []]])<br />
"afg^^c^bd^e^^^"<br />
<br />
</haskell><br />
<br />
[[99 questions/Solutions/70 | Solutions]]<br />
<br />
== Problem 71 ==<br />
<br />
(*) Determine the internal path length of a tree.<br />
<br />
We define the internal path length of a multiway tree as the total sum of the path lengths from the root to all nodes of the tree. By this definition, <tt>tree5</tt> has an internal path length of 9. <br />
<br />
Example in Haskell:<br />
<br />
<haskell><br />
λ> ipl tree5<br />
9<br />
λ> ipl tree4<br />
2<br />
</haskell><br />
<br />
[[99 questions/Solutions/71 | Solutions]]<br />
<br />
<br />
== Problem 72 ==<br />
<br />
(*) Construct the bottom-up order sequence of the tree nodes.<br />
<br />
Write a predicate bottom_up(Tree,Seq) which constructs the bottom-up sequence of the nodes of the multiway tree Tree.<br />
<br />
Example in Haskell:<br />
<br />
<haskell><br />
λ> bottom_up tree5<br />
"gfcdeba"<br />
</haskell><br />
<br />
[[99 questions/Solutions/72 | Solutions]]<br />
<br />
<br />
== Problem 73 ==<br />
<br />
(**) Lisp-like tree representation.<br />
<br />
There is a particular notation for multiway trees in Lisp. Lisp is a prominent functional programming language, which is used primarily for artificial intelligence problems. As such it is one of the main competitors of Prolog. In Lisp almost everything is a list, just as in Prolog everything is a term.<br />
<br />
The following pictures show how multiway tree structures are represented in Lisp.<br />
<br />
https://prof.ti.bfh.ch/hew1/informatik3/prolog/p-99/p73.png<br />
<br />
Note that in the "lispy" notation a node with successors (children) in the tree is always the first element in a list, followed by its children. The "lispy" representation of a multiway tree is a sequence of atoms and parentheses '(' and ')', which we shall collectively call "tokens". We can represent this sequence of tokens as a Prolog list; e.g. the lispy expression (a (b c)) could be represented as the Prolog list ['(', a, '(', b, c, ')', ')']. Write a predicate tree_ltl(T,LTL) which constructs the "lispy token list" LTL if the tree is given as term T in the usual Prolog notation.<br />
<br />
(The Prolog example given is incorrect.)<br />
<br />
Example in Haskell:<br />
<br />
<haskell><br />
λ> display lisp tree1<br />
"a"<br />
λ> display lisp tree2<br />
"(a b)"<br />
λ> display lisp tree3<br />
"(a (b c))"<br />
λ> display lisp tree4<br />
"(b d e)"<br />
λ> display lisp tree5<br />
"(a (f g) c (b d e))"<br />
</haskell><br />
<br />
As a second, even more interesting exercise try to rewrite tree_ltl/2 in a way that the inverse conversion is also possible.<br />
<br />
[[99 questions/Solutions/73 | Solutions]]<br />
<br />
<br />
[[Category:Tutorials]]</div>Wizzuphttps://wiki.haskell.org/index.php?title=99_questions/54A_to_60&diff=6276099 questions/54A to 602019-02-09T09:33:02Z<p>Wizzup: unify ghci prompts</p>
<hr />
<div>__NOTOC__<br />
<br />
This is part of [[H-99:_Ninety-Nine_Haskell_Problems|Ninety-Nine Haskell Problems]], based on [https://prof.ti.bfh.ch/hew1/informatik3/prolog/p-99/ Ninety-Nine Prolog Problems].<br />
<br />
== Binary trees ==<br />
<br />
A binary tree is either empty or it is composed of a root element and two successors, which are binary trees themselves.<br />
<br />
https://prof.ti.bfh.ch/hew1/informatik3/prolog/p-99/p67.gif<br />
<br />
In Haskell, we can characterize binary trees with a datatype definition:<br />
<br />
<haskell><br />
data Tree a = Empty | Branch a (Tree a) (Tree a)<br />
deriving (Show, Eq)<br />
</haskell><br />
<br />
This says that a <tt>Tree</tt> of type <tt>a</tt> consists of either an <tt>Empty</tt> node, or a <tt>Branch</tt> containing one value of type <tt>a</tt> with exactly two subtrees of type <tt>a</tt>.<br />
<br />
Given this definition, the tree in the diagram above would be represented as:<br />
<br />
<haskell><br />
tree1 = Branch 'a' (Branch 'b' (Branch 'd' Empty Empty)<br />
(Branch 'e' Empty Empty))<br />
(Branch 'c' Empty<br />
(Branch 'f' (Branch 'g' Empty Empty)<br />
Empty))<br />
</haskell><br />
<br />
Since a "leaf" node is a branch with two empty subtrees, it can be useful to define a shorthand function:<br />
<br />
<haskell><br />
leaf x = Branch x Empty Empty<br />
</haskell><br />
<br />
Then the tree diagram above could be expressed more simply as:<br />
<br />
<haskell><br />
tree1' = Branch 'a' (Branch 'b' (leaf 'd')<br />
(leaf 'e'))<br />
(Branch 'c' Empty<br />
(Branch 'f' (leaf 'g')<br />
Empty)))<br />
</haskell><br />
<br />
Other examples of binary trees:<br />
<br />
<haskell><br />
-- A binary tree consisting of a root node only<br />
tree2 = Branch 'a' Empty Empty<br />
<br />
-- An empty binary tree<br />
tree3 = Empty<br />
<br />
-- A tree of integers<br />
tree4 = Branch 1 (Branch 2 Empty (Branch 4 Empty Empty))<br />
(Branch 2 Empty Empty)<br />
</haskell><br />
<br />
== Problem 54A ==<br />
<br />
(*) Check whether a given term represents a binary tree<br />
<br />
In Prolog or Lisp, one writes a predicate to do this.<br />
<br />
Example in Lisp:<br />
<br />
<pre><br />
* (istree (a (b nil nil) nil))<br />
T<br />
* (istree (a (b nil nil)))<br />
NIL<br />
</pre><br />
<br />
Non-solution:<br />
<br />
Haskell's type system ensures that all terms of type <hask>Tree a</hask> are binary trees: it is just not possible to construct an invalid tree with this type. Hence, it is redundant to introduce a predicate to check this property: it would always return <hask>True</hask>.<br />
<br />
<br />
== Problem 55 ==<br />
<br />
(**) Construct completely balanced binary trees<br />
<br />
In a completely balanced binary tree, the following property holds for every node: The number of nodes in its left subtree and the number of nodes in its right subtree are almost equal, which means their difference is not greater than one.<br />
<br />
Write a function cbal-tree to construct completely balanced binary trees for a given number of nodes. The predicate should generate all solutions via backtracking. Put the letter 'x' as information into all nodes of the tree.<br />
<br />
Example:<br />
<br />
<pre><br />
* cbal-tree(4,T).<br />
T = t(x, t(x, nil, nil), t(x, nil, t(x, nil, nil))) ;<br />
T = t(x, t(x, nil, nil), t(x, t(x, nil, nil), nil)) ;<br />
etc......No<br />
</pre><br />
<br />
Example in Haskell, whitespace and "comment diagrams" added for clarity and exposition:<br />
<br />
<haskell><br />
λ> cbalTree 4<br />
[<br />
-- permutation 1<br />
-- x<br />
-- / \<br />
-- x x<br />
-- \<br />
-- x<br />
Branch 'x' (Branch 'x' Empty Empty) <br />
(Branch 'x' Empty <br />
(Branch 'x' Empty Empty)),<br />
<br />
-- permutation 2<br />
-- x<br />
-- / \<br />
-- x x<br />
-- /<br />
-- x<br />
Branch 'x' (Branch 'x' Empty Empty) <br />
(Branch 'x' (Branch 'x' Empty Empty) <br />
Empty),<br />
<br />
-- permutation 3<br />
-- x<br />
-- / \<br />
-- x x<br />
-- \<br />
-- x<br />
Branch 'x' (Branch 'x' Empty <br />
(Branch 'x' Empty Empty)) <br />
(Branch 'x' Empty Empty),<br />
<br />
-- permutation 4<br />
-- x<br />
-- / \<br />
-- x x<br />
-- /<br />
-- x<br />
Branch 'x' (Branch 'x' (Branch 'x' Empty Empty) <br />
Empty) <br />
(Branch 'x' Empty Empty)<br />
]<br />
</haskell><br />
<br />
[[99 questions/Solutions/55 | Solutions]]<br />
<br />
<br />
== Problem 56 ==<br />
<br />
(**) Symmetric binary trees<br />
<br />
Let us call a binary tree symmetric if you can draw a vertical line through the root node and then the right subtree is the mirror image of the left subtree. Write a predicate symmetric/1 to check whether a given binary tree is symmetric. Hint: Write a predicate mirror/2 first to check whether one tree is the mirror image of another. We are only interested in the structure, not in the contents of the nodes.<br />
<br />
Example in Haskell:<br />
<br />
<haskell><br />
λ> symmetric (Branch 'x' (Branch 'x' Empty Empty) Empty)<br />
False<br />
λ> symmetric (Branch 'x' (Branch 'x' Empty Empty) (Branch 'x' Empty Empty))<br />
True<br />
</haskell><br />
<br />
[[99 questions/Solutions/56 | Solutions]]<br />
<br />
<br />
== Problem 57 ==<br />
<br />
(**) Binary search trees (dictionaries)<br />
<br />
Use the predicate add/3, developed in chapter 4 of the course, to write a predicate to construct a binary search tree from a list of integer numbers.<br />
<br />
Example:<br />
<br />
<pre><br />
* construct([3,2,5,7,1],T).<br />
T = t(3, t(2, t(1, nil, nil), nil), t(5, nil, t(7, nil, nil)))<br />
</pre><br />
<br />
Then use this predicate to test the solution of the problem P56.<br />
<br />
Example:<br />
<br />
<pre><br />
* test-symmetric([5,3,18,1,4,12,21]).<br />
Yes<br />
* test-symmetric([3,2,5,7,4]).<br />
No<br />
</pre><br />
<br />
Example in Haskell:<br />
<br />
<haskell><br />
λ> construct [3, 2, 5, 7, 1]<br />
Branch 3 (Branch 2 (Branch 1 Empty Empty) Empty) (Branch 5 Empty (Branch 7 Empty Empty))<br />
λ> symmetric . construct $ [5, 3, 18, 1, 4, 12, 21]<br />
True<br />
λ> symmetric . construct $ [3, 2, 5, 7, 1]<br />
True<br />
</haskell><br />
<br />
[[99 questions/Solutions/57 | Solutions]]<br />
<br />
<br />
== Problem 58 ==<br />
<br />
(**) Generate-and-test paradigm<br />
<br />
Apply the generate-and-test paradigm to construct all symmetric, completely balanced binary trees with a given number of nodes.<br />
<br />
Example:<br />
<br />
<pre><br />
* sym-cbal-trees(5,Ts).<br />
Ts = [t(x, t(x, nil, t(x, nil, nil)), t(x, t(x, nil, nil), nil)), t(x, t(x, t(x, nil, nil), nil), t(x, nil, t(x, nil, nil)))] <br />
</pre><br />
<br />
Example in Haskell:<br />
<br />
<haskell><br />
λ> symCbalTrees 5<br />
[Branch 'x' (Branch 'x' Empty (Branch 'x' Empty Empty)) (Branch 'x' (Branch 'x' Empty Empty) Empty),Branch 'x' (Branch 'x' (Branch 'x' Empty Empty) Empty) (Branch 'x' Empty (Branch 'x' Empty Empty))]<br />
</haskell><br />
<br />
[[99 questions/Solutions/58 | Solutions]]<br />
<br />
<br />
== Problem 59 ==<br />
<br />
(**) Construct height-balanced binary trees<br />
<br />
In a height-balanced binary tree, the following property holds for every node: The height of its left subtree and the height of its right subtree are almost equal, which means their difference is not greater than one.<br />
<br />
Construct a list of all height-balanced binary trees with the given element and the given maximum height.<br />
<br />
Example:<br />
<br />
<pre><br />
?- hbal_tree(3,T).<br />
T = t(x, t(x, t(x, nil, nil), t(x, nil, nil)), t(x, t(x, nil, nil), t(x, nil, nil))) ;<br />
T = t(x, t(x, t(x, nil, nil), t(x, nil, nil)), t(x, t(x, nil, nil), nil)) ;<br />
etc......No<br />
</pre><br />
<br />
Example in Haskell:<br />
<br />
<haskell><br />
λ> take 4 $ hbalTree 'x' 3<br />
[Branch 'x' (Branch 'x' Empty Empty) (Branch 'x' Empty (Branch 'x' Empty Empty)),<br />
Branch 'x' (Branch 'x' Empty Empty) (Branch 'x' (Branch 'x' Empty Empty) Empty),<br />
Branch 'x' (Branch 'x' Empty Empty) (Branch 'x' (Branch 'x' Empty Empty) (Branch 'x' Empty Empty)),<br />
Branch 'x' (Branch 'x' Empty (Branch 'x' Empty Empty)) (Branch 'x' Empty Empty)]<br />
</haskell><br />
<br />
[[99 questions/Solutions/59 | Solutions]]<br />
<br />
== Problem 60 ==<br />
<br />
(**) Construct height-balanced binary trees with a given number of nodes<br />
<br />
Consider a height-balanced binary tree of height H. What is the maximum number of nodes it can contain?<br />
<br />
Clearly, MaxN = 2**H - 1. However, what is the minimum number MinN? This question is more difficult. Try to find a recursive statement and turn it into a function <hask>minNodes</hask> that returns the minimum number of nodes in a height-balanced binary tree of height H.<br />
<br />
On the other hand, we might ask: what is the maximum height H a height-balanced binary tree with N nodes can have? Write a function <hask>maxHeight</hask> that computes this.<br />
<br />
Now, we can attack the main problem: construct all the height-balanced binary trees with a given number of nodes. Find out how many height-balanced trees exist for N = 15.<br />
<br />
Example in Prolog:<br />
<br />
<pre><br />
?- count_hbal_trees(15,C).<br />
C = 1553<br />
</pre><br />
<br />
Example in Haskell:<br />
<br />
<haskell><br />
λ> length $ hbalTreeNodes 'x' 15<br />
1553<br />
λ> map (hbalTreeNodes 'x') [0..3]<br />
[[Empty],<br />
[Branch 'x' Empty Empty],<br />
[Branch 'x' Empty (Branch 'x' Empty Empty),Branch 'x' (Branch 'x' Empty Empty) Empty],<br />
[Branch 'x' (Branch 'x' Empty Empty) (Branch 'x' Empty Empty)]]<br />
</haskell><br />
<br />
[[99 questions/Solutions/60 | Solutions]]<br />
<br />
<br />
[[Category:Tutorials]]</div>Wizzuphttps://wiki.haskell.org/index.php?title=99_questions/46_to_50&diff=6275999 questions/46 to 502019-02-09T09:29:16Z<p>Wizzup: unify ghci prompts</p>
<hr />
<div>__NOTOC__<br />
<br />
This is part of [[H-99:_Ninety-Nine_Haskell_Problems|Ninety-Nine Haskell Problems]], based on [https://prof.ti.bfh.ch/hew1/informatik3/prolog/p-99/ Ninety-Nine Prolog Problems].<br />
<br />
== Logic and Codes ==<br />
<br />
== Problem 46 ==<br />
<br />
(**) Define predicates and/2, or/2, nand/2, nor/2, xor/2, impl/2 and equ/2 (for logical equivalence) which succeed or fail according to the result of their respective operations; e.g. and(A,B) will succeed, if and only if both A and B succeed.<br />
<br />
A logical expression in two variables can then be written as in the following example: and(or(A,B),nand(A,B)).<br />
<br />
Now, write a predicate table/3 which prints the truth table of a given logical expression in two variables.<br />
<br />
Example:<br />
<br />
<pre><br />
(table A B (and A (or A B)))<br />
true true true<br />
true fail true<br />
fail true fail<br />
fail fail fail<br />
</pre><br />
<br />
Example in Haskell:<br />
<br />
<haskell><br />
λ> table (\a b -> (and' a (or' a b)))<br />
True True True<br />
True False True<br />
False True False<br />
False False False<br />
</haskell><br />
<br />
[[99 questions/Solutions/46 | Solutions]]<br />
<br />
== Problem 47 ==<br />
<br />
(*) Truth tables for logical expressions (2).<br />
<br />
Continue problem P46 by defining and/2, or/2, etc as being operators. This allows to write the logical expression in the more natural way, as in the example: A and (A or not B). Define operator precedence as usual; i.e. as in Java.<br />
<br />
Example:<br />
<br />
<pre><br />
* (table A B (A and (A or not B)))<br />
true true true<br />
true fail true<br />
fail true fail<br />
fail fail fail<br />
</pre><br />
<br />
Example in Haskell:<br />
<br />
<haskell><br />
λ> table2 (\a b -> a `and'` (a `or'` not b))<br />
True True True<br />
True False True<br />
False True False<br />
False False False<br />
</haskell><br />
<br />
[[99 questions/Solutions/47 | Solutions]]<br />
<br />
== Problem 48 ==<br />
<br />
(**) Truth tables for logical expressions (3).<br />
<br />
Generalize problem P47 in such a way that the logical expression may contain any number of logical variables. Define table/2 in a way that table(List,Expr) prints the truth table for the expression Expr, which contains the logical variables enumerated in List.<br />
<br />
Example:<br />
<br />
<pre><br />
* (table (A,B,C) (A and (B or C) equ A and B or A and C))<br />
true true true true<br />
true true fail true<br />
true fail true true<br />
true fail fail true<br />
fail true true true<br />
fail true fail true<br />
fail fail true true<br />
fail fail fail true<br />
</pre><br />
<br />
Example in Haskell:<br />
<br />
<haskell><br />
λ> tablen 3 (\[a,b,c] -> a `and'` (b `or'` c) `equ'` a `and'` b `or'` a `and'` c)<br />
-- infixl 3 `equ'`<br />
True True True True<br />
True True False True<br />
True False True True<br />
True False False True<br />
False True True True<br />
False True False True<br />
False False True True<br />
False False False True<br />
<br />
-- infixl 7 `equ'`<br />
True True True True<br />
True True False True<br />
True False True True<br />
True False False False<br />
False True True False<br />
False True False False<br />
False False True False<br />
False False False False<br />
</haskell><br />
<br />
[[99 questions/Solutions/48 | Solutions]]<br />
<br />
== Problem 49 ==<br />
<br />
(**) Gray codes.<br />
<br />
An n-bit Gray code is a sequence of n-bit strings constructed according to certain rules. For example,<br />
<br />
<pre><br />
n = 1: C(1) = ['0','1'].<br />
n = 2: C(2) = ['00','01','11','10'].<br />
n = 3: C(3) = ['000','001','011','010',´110´,´111´,´101´,´100´].<br />
</pre><br />
<br />
Find out the construction rules and write a predicate with the following specification:<br />
<br />
<pre><br />
% gray(N,C) :- C is the N-bit Gray code<br />
</pre><br />
<br />
Can you apply the method of "result caching" in order to make the predicate more efficient, when it is to be used repeatedly?<br />
<br />
Example in Haskell:<br />
<br />
<haskell><br />
λ> gray 3<br />
["000","001","011","010","110","111","101","100"]<br />
</haskell><br />
<br />
[[99 questions/Solutions/49 | Solutions]]<br />
<br />
<br />
== Problem 50 ==<br />
<br />
(***) Huffman codes.<br />
<br />
We suppose a set of symbols with their frequencies, given as a list of fr(S,F) terms. Example: [fr(a,45),fr(b,13),fr(c,12),fr(d,16),fr(e,9),fr(f,5)]. Our objective is to construct a list hc(S,C) terms, where C is the Huffman code word for the symbol S. In our example, the result could be Hs = [hc(a,'0'), hc(b,'101'), hc(c,'100'), hc(d,'111'), hc(e,'1101'), hc(f,'1100')] [hc(a,'01'),...etc.]. The task shall be performed by the predicate huffman/2 defined as follows: <br />
<br />
<pre><br />
% huffman(Fs,Hs) :- Hs is the Huffman code table for the frequency table Fs<br />
</pre><br />
<br />
Example in Haskell:<br />
<haskell><br />
λ> huffman [('a',45),('b',13),('c',12),('d',16),('e',9),('f',5)]<br />
[('a',"0"),('b',"101"),('c',"100"),('d',"111"),('e',"1101"),('f',"1100")]<br />
</haskell><br />
<br />
[[99 questions/Solutions/50 | Solutions]]<br />
<br />
[[Category:Tutorials]]</div>Wizzuphttps://wiki.haskell.org/index.php?title=99_questions/31_to_41&diff=6275899 questions/31 to 412019-02-09T09:15:29Z<p>Wizzup: unify ghci prompts</p>
<hr />
<div>__NOTOC__<br />
<br />
This is part of [[H-99:_Ninety-Nine_Haskell_Problems|Ninety-Nine Haskell Problems]], based on [https://prof.ti.bfh.ch/hew1/informatik3/prolog/p-99/ Ninety-Nine Prolog Problems].<br />
<br />
== Problem 31 ==<br />
<br />
(**) Determine whether a given integer number is prime.<br />
<br />
Example:<br />
<br />
<pre><br />
* (is-prime 7)<br />
T<br />
</pre><br />
<br />
Example in Haskell:<br />
<br />
<haskell><br />
λ> isPrime 7<br />
True<br />
</haskell><br />
<br />
[[99 questions/Solutions/31 | Solutions]]<br />
<br />
<br />
== Problem 32 ==<br />
<br />
(**) Determine the greatest common divisor of two positive integer numbers. Use [http://en.wikipedia.org/wiki/Euclidean_algorithm Euclid's algorithm].<br />
<br />
Example:<br />
<br />
<pre><br />
* (gcd 36 63)<br />
9<br />
</pre><br />
<br />
Example in Haskell:<br />
<br />
<haskell><br />
λ> [myGCD 36 63, myGCD (-3) (-6), myGCD (-3) 6]<br />
[9,3,3]<br />
</haskell><br />
<br />
[[99 questions/Solutions/32 | Solutions]]<br />
<br />
== Problem 33 ==<br />
<br />
(*) Determine whether two positive integer numbers are coprime. Two numbers are coprime if their greatest common divisor equals 1.<br />
<br />
Example:<br />
<br />
<pre><br />
* (coprime 35 64)<br />
T<br />
</pre><br />
<br />
Example in Haskell:<br />
<br />
<haskell><br />
λ> coprime 35 64<br />
True <br />
</haskell><br />
<br />
[[99 questions/Solutions/33 | Solutions]]<br />
<br />
<br />
== Problem 34 ==<br />
<br />
(**) Calculate Euler's totient function phi(m).<br />
<br />
Euler's so-called totient function phi(m) is defined as the number of positive integers r (1 <= r < m) that are coprime to m.<br />
<br />
Example: m = 10: r = 1,3,7,9; thus phi(m) = 4. Note the special case: phi(1) = 1.<br />
<br />
Example:<br />
<br />
<pre><br />
* (totient-phi 10)<br />
4<br />
</pre><br />
<br />
Example in Haskell:<br />
<br />
<haskell><br />
λ> totient 10<br />
4<br />
</haskell><br />
<br />
[[99 questions/Solutions/34 | Solutions]]<br />
<br />
<br />
== Problem 35 ==<br />
<br />
(**) Determine the prime factors of a given positive integer. Construct a flat list containing the prime factors in ascending order.<br />
<br />
Example:<br />
<br />
<pre><br />
* (prime-factors 315)<br />
(3 3 5 7)<br />
</pre><br />
<br />
Example in Haskell:<br />
<br />
<haskell><br />
λ> primeFactors 315<br />
[3, 3, 5, 7]<br />
</haskell><br />
<br />
[[99 questions/Solutions/35 | Solutions]]<br />
<br />
<br />
== Problem 36 ==<br />
<br />
(**) Determine the prime factors of a given positive integer.<br />
<br />
Construct a list containing the prime factors and their multiplicity.<br />
<br />
Example:<br />
<br />
<pre><br />
* (prime-factors-mult 315)<br />
((3 2) (5 1) (7 1))<br />
</pre><br />
<br />
Example in Haskell:<br />
<br />
<haskell><br />
λ> prime_factors_mult 315<br />
[(3,2),(5,1),(7,1)]<br />
</haskell><br />
<br />
[[99 questions/Solutions/36 | Solutions]]<br />
<br />
<br />
== Problem 37 ==<br />
<br />
(**) Calculate Euler's totient function phi(m) (improved).<br />
<br />
See problem 34 for the definition of Euler's totient function. If the list of the prime factors of a number m is known in the form of problem 36 then the function phi(m) can be efficiently calculated as follows: Let ((p1 m1) (p2 m2) (p3 m3) ...) be the list of prime factors (and their multiplicities) of a given number m. Then phi(m) can be calculated with the following formula:<br />
<br />
<pre><br />
phi(m) = (p1 - 1) * p1 ** (m1 - 1) * <br />
(p2 - 1) * p2 ** (m2 - 1) * <br />
(p3 - 1) * p3 ** (m3 - 1) * ...<br />
</pre><br />
<br />
Note that a ** b stands for the b'th power of a.<br />
<br />
[[99 questions/Solutions/37 | Solutions]]<br />
<br />
== Problem 38 ==<br />
<br />
(*) Compare the two methods of calculating Euler's totient function.<br />
<br />
Use the solutions of problems 34 and 37 to compare the algorithms. Take the number of reductions as a measure for efficiency. Try to calculate phi(10090) as an example.<br />
<br />
(no solution required)<br />
<br />
<br />
== Problem 39 ==<br />
<br />
(*) A list of prime numbers.<br />
<br />
Given a range of integers by its lower and upper limit, construct a list of all prime numbers in that range.<br />
<br />
Example in Haskell:<br />
<br />
<haskell><br />
λ> primesR 10 20<br />
[11,13,17,19]<br />
</haskell><br />
<br />
[[99 questions/Solutions/39 | Solutions]]<br />
<br />
<br />
== Problem 40 ==<br />
<br />
(**) Goldbach's conjecture.<br />
<br />
Goldbach's conjecture says that every positive even number greater than 2 is the sum of two prime numbers. Example: 28 = 5 + 23. It is one of the most famous facts in number theory that has not been proved to be correct in the general case. It has been numerically confirmed up to very large numbers (much larger than we can go with our Prolog system). Write a predicate to find the two prime numbers that sum up to a given even integer.<br />
<br />
Example:<br />
<br />
<pre><br />
* (goldbach 28)<br />
(5 23)<br />
</pre><br />
<br />
Example in Haskell:<br />
<br />
<haskell><br />
λ> goldbach 28<br />
(5, 23)<br />
</haskell><br />
<br />
[[99 questions/Solutions/40 | Solutions]]<br />
<br />
<br />
== Problem 41 ==<br />
<br />
(**) Given a range of integers by its lower and upper limit, print a list of all even numbers and their Goldbach composition.<br />
<br />
In most cases, if an even number is written as the sum of two prime numbers, one of them is very small. Very rarely, the primes are both bigger than say 50. Try to find out how many such cases there are in the range 2..3000.<br />
<br />
Example:<br />
<br />
<pre><br />
* (goldbach-list 9 20)<br />
10 = 3 + 7<br />
12 = 5 + 7<br />
14 = 3 + 11<br />
16 = 3 + 13<br />
18 = 5 + 13<br />
20 = 3 + 17<br />
* (goldbach-list 1 2000 50)<br />
992 = 73 + 919<br />
1382 = 61 + 1321<br />
1856 = 67 + 1789<br />
1928 = 61 + 1867<br />
</pre><br />
<br />
Example in Haskell:<br />
<br />
<haskell><br />
λ> goldbachList 9 20<br />
[(3,7),(5,7),(3,11),(3,13),(5,13),(3,17)]<br />
λ> goldbachList' 4 2000 50<br />
[(73,919),(61,1321),(67,1789),(61,1867)]<br />
</haskell><br />
<br />
[[99 questions/Solutions/41 | Solutions]]<br />
<br />
<br />
[[Category:Tutorials]]</div>Wizzuphttps://wiki.haskell.org/index.php?title=99_questions/1_to_10&diff=6275799 questions/1 to 102019-02-09T09:06:58Z<p>Wizzup: /* Problem 8 */</p>
<hr />
<div>__NOTOC__<br />
<br />
This is part of [[H-99:_Ninety-Nine_Haskell_Problems|Ninety-Nine Haskell Problems]], based on [https://sites.google.com/site/prologsite/prolog-problems Ninety-Nine Prolog Problems] and [http://www.ic.unicamp.br/~meidanis/courses/mc336/2006s2/funcional/L-99_Ninety-Nine_Lisp_Problems.html Ninety-Nine Lisp Problems].<br />
<br />
== Problem 1 ==<br />
<br />
(*) Find the last element of a list.<br />
<br />
(Note that the Lisp transcription of this problem is incorrect.)<br />
<br />
Example in Haskell:<br />
<br />
<haskell><br />
λ> myLast [1,2,3,4]<br />
4<br />
λ> myLast ['x','y','z']<br />
'z'<br />
</haskell><br />
<br />
[[99 questions/Solutions/1 | Solutions]]<br />
<br />
<br />
== Problem 2 ==<br />
<br />
(*) Find the last but one element of a list.<br />
<br />
(Note that the Lisp transcription of this problem is incorrect.)<br />
<br />
Example in Haskell:<br />
<br />
<haskell><br />
λ> myButLast [1,2,3,4]<br />
3<br />
λ> myButLast ['a'..'z']<br />
'y'<br />
</haskell><br />
<br />
[[99 questions/Solutions/2 | Solutions]]<br />
<br />
<br />
== Problem 3 ==<br />
<br />
(*) Find the K'th element of a list. The first element in the list is number 1.<br />
<br />
Example:<br />
<br />
<pre><br />
* (element-at '(a b c d e) 3)<br />
c<br />
</pre><br />
<br />
Example in Haskell:<br />
<br />
<haskell><br />
λ> elementAt [1,2,3] 2<br />
2<br />
λ> elementAt "haskell" 5<br />
'e'<br />
</haskell><br />
<br />
[[99 questions/Solutions/3 | Solutions]]<br />
<br />
<br />
== Problem 4 ==<br />
<br />
(*) Find the number of elements of a list.<br />
<br />
Example in Haskell:<br />
<br />
<haskell><br />
λ> myLength [123, 456, 789]<br />
3<br />
λ> myLength "Hello, world!"<br />
13<br />
</haskell><br />
<br />
[[99 questions/Solutions/4 | Solutions]]<br />
<br />
<br />
== Problem 5 ==<br />
<br />
(*) Reverse a list.<br />
<br />
Example in Haskell:<br />
<br />
<haskell><br />
λ> myReverse "A man, a plan, a canal, panama!"<br />
"!amanap ,lanac a ,nalp a ,nam A"<br />
λ> myReverse [1,2,3,4]<br />
[4,3,2,1]<br />
</haskell><br />
<br />
[[99 questions/Solutions/5 | Solutions]]<br />
<br />
<br />
== Problem 6 ==<br />
<br />
(*) Find out whether a list is a palindrome. A palindrome can be read forward or backward; e.g. (x a m a x).<br />
<br />
Example in Haskell:<br />
<br />
<haskell><br />
λ> isPalindrome [1,2,3]<br />
False<br />
λ> isPalindrome "madamimadam"<br />
True<br />
λ> isPalindrome [1,2,4,8,16,8,4,2,1]<br />
True<br />
</haskell><br />
<br />
[[99 questions/Solutions/6 | Solutions]]<br />
<br />
<br />
== Problem 7 ==<br />
<br />
(**) Flatten a nested list structure.<br />
<br />
Transform a list, possibly holding lists as elements into a `flat' list by replacing each list with its elements (recursively).<br />
<br />
Example:<br />
<br />
<pre><br />
* (my-flatten '(a (b (c d) e)))<br />
(A B C D E)<br />
</pre><br />
<br />
Example in Haskell:<br />
<br />
We have to define a new data type, because lists in Haskell are homogeneous. <br />
<haskell><br />
data NestedList a = Elem a | List [NestedList a]<br />
</haskell><br />
<br />
<haskell><br />
λ> flatten (Elem 5)<br />
[5]<br />
λ> flatten (List [Elem 1, List [Elem 2, List [Elem 3, Elem 4], Elem 5]])<br />
[1,2,3,4,5]<br />
λ> flatten (List [])<br />
[]<br />
</haskell><br />
<br />
<br />
<br />
[[99 questions/Solutions/7 | Solutions]]<br />
<br />
== Problem 8 ==<br />
<br />
(**) Eliminate consecutive duplicates of list elements.<br />
<br />
If a list contains repeated elements they should be replaced with a single copy of the element. The order of the elements should not be changed.<br />
<br />
Example:<br />
<br />
<pre><br />
* (compress '(a a a a b c c a a d e e e e))<br />
(A B C A D E)<br />
</pre><br />
<br />
Example in Haskell:<br />
<br />
<haskell><br />
λ> compress "aaaabccaadeeee"<br />
"abcade"<br />
</haskell><br />
<br />
[[99 questions/Solutions/8 | Solutions]]<br />
<br />
== Problem 9 ==<br />
<br />
(**) Pack consecutive duplicates of list elements into sublists.<br />
If a list contains repeated elements they should be placed in separate sublists.<br />
<br />
Example:<br />
<br />
<pre><br />
* (pack '(a a a a b c c a a d e e e e))<br />
((A A A A) (B) (C C) (A A) (D) (E E E E))<br />
</pre><br />
<br />
Example in Haskell:<br />
<br />
<haskell><br />
λ> pack ['a', 'a', 'a', 'a', 'b', 'c', 'c', 'a', <br />
'a', 'd', 'e', 'e', 'e', 'e']<br />
["aaaa","b","cc","aa","d","eeee"]<br />
</haskell><br />
<br />
[[99 questions/Solutions/9 | Solutions]]<br />
<br />
== Problem 10 ==<br />
<br />
(*) Run-length encoding of a list.<br />
Use the result of problem P09 to implement the so-called run-length encoding data compression method. Consecutive duplicates of elements are encoded as lists (N E) where N is the number of duplicates of the element E.<br />
<br />
Example:<br />
<pre><br />
* (encode '(a a a a b c c a a d e e e e))<br />
((4 A) (1 B) (2 C) (2 A) (1 D)(4 E))<br />
</pre><br />
<br />
Example in Haskell:<br />
<haskell><br />
λ> encode "aaaabccaadeeee"<br />
[(4,'a'),(1,'b'),(2,'c'),(2,'a'),(1,'d'),(4,'e')]<br />
</haskell><br />
<br />
[[99 questions/Solutions/10 | Solutions]]<br />
<br />
<br />
[[Category:Tutorials]]</div>Wizzuphttps://wiki.haskell.org/index.php?title=99_questions/95_to_99&diff=6275699 questions/95 to 992019-02-09T02:14:31Z<p>Wizzup: </p>
<hr />
<div>__NOTOC__<br />
<br />
This is part of [[H-99:_Ninety-Nine_Haskell_Problems|Ninety-Nine Haskell Problems]], based on [https://prof.ti.bfh.ch/hew1/informatik3/prolog/p-99/ Ninety-Nine Prolog Problems].<br />
<br />
== Problem 95 ==<br />
<br />
(**) English number words<br />
<br />
On financial documents, like cheques, numbers must sometimes be written in full words. Example: 175 must be written as one-seven-five. Write a predicate full-words/1 to print (non-negative) integer numbers in full words.<br />
<br />
Example in Haskell:<br />
<br />
<haskell><br />
> fullWords 175<br />
one-seven-five<br />
</haskell><br />
<br />
[[99 questions/Solutions/95 | Solutions]]<br />
<br />
<br />
== Problem 96 ==<br />
<br />
(**) Syntax checker<br />
<br />
In a certain programming language (Ada) identifiers are defined by the syntax diagram below.<br />
<br />
https://prof.ti.bfh.ch/hew1/informatik3/prolog/p-99/p96.gif<br />
<br />
Transform the syntax diagram into a system of syntax diagrams which do not contain loops; i.e. which are purely recursive. Using these modified diagrams, write a predicate identifier/1 that can check whether or not a given string is a legal identifier.<br />
<br />
Example in Prolog:<br />
<br />
<pre><br />
% identifier(Str) :- Str is a legal identifier <br />
</pre><br />
<br />
Example in Haskell:<br />
<br />
<haskell><br />
> identifier "this-is-a-long-identifier"<br />
True<br />
> identifier "this-ends-in-" <br />
False<br />
> identifier "two--hyphens" <br />
False<br />
</haskell><br />
<br />
[[99 questions/Solutions/96 | Solutions]]<br />
<br />
<br />
== Problem 97 ==<br />
<br />
(**) Sudoku<br />
<br />
Sudoku puzzles go like this:<br />
<br />
<pre><br />
Problem statement Solution<br />
<br />
. . 4 | 8 . . | . 1 7 9 3 4 | 8 2 5 | 6 1 7 <br />
| | | |<br />
6 7 . | 9 . . | . . . 6 7 2 | 9 1 4 | 8 5 3<br />
| | | |<br />
5 . 8 | . 3 . | . . 4 5 1 8 | 6 3 7 | 9 2 4<br />
--------+---------+-------- --------+---------+--------<br />
3 . . | 7 4 . | 1 . . 3 2 5 | 7 4 8 | 1 6 9<br />
| | | |<br />
. 6 9 | . . . | 7 8 . 4 6 9 | 1 5 3 | 7 8 2<br />
| | | |<br />
. . 1 | . 6 9 | . . 5 7 8 1 | 2 6 9 | 4 3 5<br />
--------+---------+-------- --------+---------+--------<br />
1 . . | . 8 . | 3 . 6 1 9 7 | 5 8 2 | 3 4 6<br />
| | | |<br />
. . . | . . 6 | . 9 1 8 5 3 | 4 7 6 | 2 9 1<br />
| | | |<br />
2 4 . | . . 1 | 5 . . 2 4 6 | 3 9 1 | 5 7 8<br />
</pre> <br />
<br />
Every spot in the puzzle belongs to a (horizontal) row and a (vertical) column, as well as to one single 3x3 square (which we call "square" for short). At the beginning, some of the spots carry a single-digit number between 1 and 9. The problem is to fill the missing spots with digits in such a way that every number between 1 and 9 appears exactly once in each row, in each column, and in each square. <br />
<br />
[[99 questions/Solutions/97 | Solutions]]<br />
<br />
<br />
== Problem 98 ==<br />
<br />
(***) Nonograms<br />
<br />
Around 1994, a certain kind of puzzle was very popular in England. The "Sunday Telegraph" newspaper wrote: "Nonograms are puzzles from Japan and are currently published each week only in The Sunday Telegraph. Simply use your logic and skill to complete the grid and reveal a picture or diagram." As a Prolog programmer, you are in a better situation: you can have your computer do the work! Just write a little program ;-).<br />
<br />
The puzzle goes like this: Essentially, each row and column of a rectangular bitmap is annotated with the respective lengths of its distinct strings of occupied cells. The person who solves the puzzle must complete the bitmap given only these lengths.<br />
<br />
Problem statement: Solution:<br />
<br />
|_|_|_|_|_|_|_|_| 3 |_|X|X|X|_|_|_|_| 3 <br />
|_|_|_|_|_|_|_|_| 2 1 |X|X|_|X|_|_|_|_| 2 1 <br />
|_|_|_|_|_|_|_|_| 3 2 |_|X|X|X|_|_|X|X| 3 2 <br />
|_|_|_|_|_|_|_|_| 2 2 |_|_|X|X|_|_|X|X| 2 2 <br />
|_|_|_|_|_|_|_|_| 6 |_|_|X|X|X|X|X|X| 6 <br />
|_|_|_|_|_|_|_|_| 1 5 |X|_|X|X|X|X|X|_| 1 5 <br />
|_|_|_|_|_|_|_|_| 6 |X|X|X|X|X|X|_|_| 6 <br />
|_|_|_|_|_|_|_|_| 1 |_|_|_|_|X|_|_|_| 1 <br />
|_|_|_|_|_|_|_|_| 2 |_|_|_|X|X|_|_|_| 2 <br />
1 3 1 7 5 3 4 3 1 3 1 7 5 3 4 3 <br />
2 1 5 1 2 1 5 1 <br />
<br />
<br />
For the example above, the problem can be stated as the two lists [[3],[2,1],[3,2],[2,2],[6],[1,5],[6],[1],[2]] and [[1,2],[3,1],[1,5],[7,1],[5],[3],[4],[3]] which give the "solid" lengths of the rows and columns, top-to-bottom and left-to-right, respectively. Published puzzles are larger than this example, e.g. 25 x 20, and apparently always have unique solutions.<br />
<br />
Example in Haskell:<br />
<br />
<haskell><br />
Nonogram> putStr $ nonogram [[3],[2,1],[3,2],[2,2],[6],[1,5],[6],[1],[2]] [[1,2],[3,1],[1,5],[7,1],[5],[3],[4],[3]]<br />
|_|X|X|X|_|_|_|_| 3<br />
|X|X|_|X|_|_|_|_| 2 1<br />
|_|X|X|X|_|_|X|X| 3 2<br />
|_|_|X|X|_|_|X|X| 2 2<br />
|_|_|X|X|X|X|X|X| 6<br />
|X|_|X|X|X|X|X|_| 1 5<br />
|X|X|X|X|X|X|_|_| 6<br />
|_|_|_|_|X|_|_|_| 1<br />
|_|_|_|X|X|_|_|_| 2<br />
1 3 1 7 5 3 4 3<br />
2 1 5 1 <br />
</haskell><br />
<br />
[[99 questions/Solutions/98 | Solutions]]<br />
<br />
<br />
== Problem 99 ==<br />
<br />
(***) Crossword puzzle<br />
<br />
Given an empty (or almost empty) framework of a crossword puzzle and a set of words. The problem is to place the words into the framework.<br />
<br />
https://prof.ti.bfh.ch/hew1/informatik3/prolog/p-99/p99.gif<br />
<br />
The particular crossword puzzle is specified in a text file which first lists the words (one word per line) in an arbitrary order. Then, after an empty line, the crossword framework is defined. In this framework specification, an empty character location is represented by a dot (.). In order to make the solution easier, character locations can also contain predefined character values. The puzzle above is defined in the file [https://sites.google.com/site/prologsite/prolog-problems/7/solutions-7/p7_09a.dat?attredirects=0&d=1 p7_09a.dat], other examples are [https://sites.google.com/site/prologsite/prolog-problems/7/solutions-7/p7_09b.dat?attredirects=0&d=1 p7_09b.dat] and [https://sites.google.com/site/prologsite/prolog-problems/7/solutions-7/p7_09d.dat?attredirects=0&d=1 p7_09d.dat]. There is also an example of a puzzle ([https://sites.google.com/site/prologsite/prolog-problems/7/solutions-7/p7_09c.dat?attredirects=0&d=1 p7_09c.dat]) which does not have a solution.<br />
<br />
Words are strings (character lists) of at least two characters. A horizontal or vertical sequence of character places in the crossword puzzle framework is called a site. Our problem is to find a compatible way of placing words onto sites.<br />
<br />
Hints: (1) The problem is not easy. You will need some time to thoroughly understand it. So, don't give up too early! And remember that the objective is a clean solution, not just a quick-and-dirty hack!<br />
<br />
(2) Reading the data file is a tricky problem for which a solution is provided in the file [https://sites.google.com/site/prologsite/prolog-problems/7/solutions-7/p7_09-readfile.pl?attredirects=0&d=1 p7_09-readfile.pl]. See the predicate read_lines/2.<br />
<br />
(3) For efficiency reasons it is important, at least for larger puzzles, to sort the words and the sites in a particular order. For this part of the problem, the solution of P28 may be very helpful. <br />
<br />
Example in Haskell:<br />
<br />
<pre><br />
ALPHA<br />
ARES<br />
POPPY<br />
<br />
.<br />
.<br />
.....<br />
. .<br />
. .<br />
.<br />
</pre><br />
<br />
<haskell><br />
> solve $ readCrossword "ALPHA\nARES\nPOPPY\n\n . \n . \n.....\n . .\n . .\n .\n"<br />
<br />
[[((3,1),'A'),((3,2),'L'),((3,3),'P'),((3,4),'H'),((3,5),'A'),((1,3),'P'),((2,3)<br />
,'O'),((3,3),'P'),((4,3),'P'),((5,3),'Y'),((3,5),'A'),((4,5),'R'),((5,5),'E'),((<br />
6,5),'S')]]<br />
</haskell><br />
<br />
[[99 questions/Solutions/99 | Solutions]]<br />
<br />
<br />
[[Category:Tutorials]]</div>Wizzuphttps://wiki.haskell.org/index.php?title=99_questions/90_to_94&diff=6275599 questions/90 to 942019-02-09T02:14:14Z<p>Wizzup: </p>
<hr />
<div>__NOTOC__<br />
<br />
This is part of [[H-99:_Ninety-Nine_Haskell_Problems|Ninety-Nine Haskell Problems]], based on [https://prof.ti.bfh.ch/hew1/informatik3/prolog/p-99/ Ninety-Nine Prolog Problems].<br />
<br />
If you want to work on one of these, put your name in the block so we know someone's working on it. Then, change n in your block to the appropriate problem number, and fill in the <Problem description>,<example in Haskell>,<solution in haskell> and <description of implementation> fields. <br />
<br />
== Problem 90 ==<br />
<br />
(**) Eight queens problem<br />
<br />
This is a classical problem in computer science. The objective is to place eight queens on a chessboard so that no two queens are attacking each other; i.e., no two queens are in the same row, the same column, or on the same diagonal.<br />
<br />
Hint: Represent the positions of the queens as a list of numbers 1..N. Example: [4,2,7,3,6,8,5,1] means that the queen in the first column is in row 4, the queen in the second column is in row 2, etc. Use the generate-and-test paradigm.<br />
<br />
Example in Haskell:<br />
<br />
<haskell><br />
> length (queens 8)<br />
92<br />
> head (queens 8)<br />
[1,5,8,6,3,7,2,4]<br />
</haskell><br />
<br />
[[99 questions/Solutions/90 | Solutions]]<br />
<br />
<br />
== Problem 91 ==<br />
<br />
(**) Knight's tour<br />
<br />
Another famous problem is this one: How can a knight jump on an NxN chessboard in such a way that it visits every square exactly once? A set of solutions is given on the [[The_Knights_Tour]] page.<br />
<br />
Hints: Represent the squares by pairs of their coordinates of the form X/Y, where both X and Y are integers between 1 and N. (Note that '/' is just a convenient functor, not division!) Define the relation jump(N,X/Y,U/V) to express the fact that a knight can jump from X/Y to U/V on a NxN chessboard. And finally, represent the solution of our problem as a list of N*N knight positions (the knight's tour).<br />
<br />
There are two variants of this problem:<br />
# find a tour ending at a particular square<br />
# find a circular tour, ending a knight's jump from the start (clearly it doesn't matter where you start, so choose (1,1))<br />
<br />
Example in Haskell:<br />
<br />
<haskell><br />
Knights> head $ knightsTo 8 (1,1)<br />
[(2,7),(3,5),(5,6),(4,8),(3,6),(4,4),(6,5),(4,6),<br />
(5,4),(7,5),(6,3),(5,5),(4,3),(2,4),(1,6),(2,8),<br />
(4,7),(6,8),(8,7),(6,6),(4,5),(6,4),(5,2),(7,1),<br />
(8,3),(6,2),(8,1),(7,3),(8,5),(7,7),(5,8),(3,7),<br />
(1,8),(2,6),(3,4),(1,5),(2,3),(3,1),(1,2),(3,3),<br />
(1,4),(2,2),(4,1),(5,3),(7,4),(8,2),(6,1),(4,2),<br />
(2,1),(1,3),(2,5),(1,7),(3,8),(5,7),(7,8),(8,6),<br />
(6,7),(8,8),(7,6),(8,4),(7,2),(5,1),(3,2),(1,1)]<br />
Knights> head $ closedKnights 8 <br />
[(1,1),(3,2),(1,3),(2,1),(3,3),(5,4),(6,6),(4,5),<br />
(2,6),(1,8),(3,7),(5,8),(4,6),(2,5),(4,4),(5,6),<br />
(6,4),(8,5),(7,7),(6,5),(5,3),(6,1),(4,2),(6,3),<br />
(8,2),(7,4),(5,5),(3,4),(1,5),(2,7),(4,8),(3,6),<br />
(1,7),(3,8),(5,7),(7,8),(8,6),(6,7),(8,8),(7,6),<br />
(8,4),(7,2),(5,1),(4,3),(3,5),(1,4),(2,2),(4,1),<br />
(6,2),(8,1),(7,3),(5,2),(7,1),(8,3),(7,5),(8,7),<br />
(6,8),(4,7),(2,8),(1,6),(2,4),(1,2),(3,1),(2,3)]<br />
</haskell><br />
<br />
[[99 questions/Solutions/91 | Solutions]]<br />
<br />
<br />
== Problem 92 ==<br />
<br />
(***) Von Koch's conjecture<br />
<br />
Several years ago I met a mathematician who was intrigued by a problem for which he didn't know a solution. His name was Von Koch, and I don't know whether the problem has been solved since.<br />
<br />
https://prof.ti.bfh.ch/hew1/informatik3/prolog/p-99/p92a.gif<br />
<br />
Anyway the puzzle goes like this: Given a tree with N nodes (and hence N-1 edges). Find a way to enumerate the nodes from 1 to N and, accordingly, the edges from 1 to N-1 in such a way, that for each edge K the difference of its node numbers equals to K. The conjecture is that this is always possible.<br />
<br />
For small trees the problem is easy to solve by hand. However, for larger trees, and 14 is already very large, it is extremely difficult to find a solution. And remember, we don't know for sure whether there is always a solution!<br />
<br />
Write a predicate that calculates a numbering scheme for a given tree. What is the solution for the larger tree pictured below?<br />
<br />
https://prof.ti.bfh.ch/hew1/informatik3/prolog/p-99/p92b.gif<br />
<br />
Example in Haskell:<br />
<br />
<haskell><br />
> head $ vonKoch [(1,6),(2,6),(3,6),(4,6),(5,6),(5,7),(5,8),(8,9),(5,10),(10,11),(11,12),(11,13),(13,14)]<br />
[6,7,8,9,3,4,10,11,5,12,2,13,14,1]<br />
</haskell><br />
<br />
[[99 questions/Solutions/92 | Solutions]]<br />
<br />
<br />
== Problem 93 ==<br />
<br />
(***) An arithmetic puzzle<br />
<br />
Given a list of integer numbers, find a correct way of inserting arithmetic signs (operators) such that the result is a correct equation. Example: With the list of numbers [2,3,5,7,11] we can form the equations 2-3+5+7 = 11 or 2 = (3*5+7)/11 (and ten others!).<br />
<br />
Division should be interpreted as operating on rationals, and division by zero should be avoided.<br />
<br />
Example in Haskell:<br />
<br />
<haskell><br />
P93> mapM_ putStrLn $ puzzle [2,3,5,7,11]<br />
2 = 3-(5+7-11)<br />
2 = 3-5-(7-11)<br />
2 = 3-(5+7)+11<br />
2 = 3-5-7+11<br />
2 = (3*5+7)/11<br />
2*(3-5) = 7-11<br />
2-(3-(5+7)) = 11<br />
2-(3-5-7) = 11<br />
2-(3-5)+7 = 11<br />
2-3+5+7 = 11<br />
</haskell><br />
<br />
The other two solutions alluded to in the problem description are dropped by the Haskell solution as trivial variants:<br />
<br />
<pre><br />
2 = 3-(5+(7-11))<br />
2-3+(5+7) = 11<br />
</pre><br />
<br />
[[99 questions/Solutions/93 | Solutions]]<br />
<br />
<br />
== Problem 94 ==<br />
<br />
(***) Generate K-regular simple graphs with N nodes<br />
<br />
In a K-regular graph all nodes have a degree of K; i.e. the number of edges incident in each node is K. How many (non-isomorphic!) 3-regular graphs with 6 nodes are there?<br />
<br />
[https://prof.ti.bfh.ch/hew1/informatik3/prolog/p-99/p94.txt Sample results]<br />
<br />
Example in Haskell:<br />
<haskell><br />
length $ regular 6 3<br />
2<br />
</haskell><br />
<br />
[[99 questions/Solutions/94 | Solutions]]<br />
<br />
[[Category:Tutorials]]</div>Wizzuphttps://wiki.haskell.org/index.php?title=99_questions/21_to_28&diff=6275499 questions/21 to 282019-02-08T08:41:44Z<p>Wizzup: unify ghci prompts</p>
<hr />
<div>__NOTOC__<br />
<br />
This is part of [[H-99:_Ninety-Nine_Haskell_Problems|Ninety-Nine Haskell Problems]], based on [https://prof.ti.bfh.ch/hew1/informatik3/prolog/p-99/ Ninety-Nine Prolog Problems] and [http://www.ic.unicamp.br/~meidanis/courses/mc336/2006s2/funcional/L-99_Ninety-Nine_Lisp_Problems.html Ninety-Nine Lisp Problems].<br />
<br />
== Problem 21 ==<br />
<br />
Insert an element at a given position into a list.<br />
<br />
Example:<br />
<br />
<pre><br />
* (insert-at 'alfa '(a b c d) 2)<br />
(A ALFA B C D)<br />
</pre><br />
<br />
Example in Haskell:<br />
<haskell><br />
λ> insertAt 'X' "abcd" 2<br />
"aXbcd"<br />
</haskell><br />
<br />
[[99 questions/Solutions/21 | Solutions]]<br />
<br />
<br />
== Problem 22 ==<br />
<br />
Create a list containing all integers within a given range.<br />
<br />
Example:<br />
<br />
<pre><br />
* (range 4 9)<br />
(4 5 6 7 8 9)<br />
</pre><br />
<br />
Example in Haskell:<br />
<br />
<haskell><br />
λ> range 4 9<br />
[4,5,6,7,8,9]<br />
</haskell><br />
<br />
[[99 questions/Solutions/22 | Solutions]]<br />
<br />
== Problem 23 ==<br />
<br />
Extract a given number of randomly selected elements from a list. <br />
<br />
Example:<br />
<br />
<pre><br />
* (rnd-select '(a b c d e f g h) 3)<br />
(E D A)<br />
</pre><br />
<br />
Example in Haskell:<br />
<br />
<haskell><br />
λ> rnd_select "abcdefgh" 3 >>= putStrLn<br />
eda<br />
</haskell><br />
<br />
[[99 questions/Solutions/23 | Solutions]]<br />
<br />
<br />
== Problem 24 ==<br />
<br />
Lotto: Draw N different random numbers from the set 1..M.<br />
<br />
Example:<br />
<br />
<pre><br />
* (rnd-select 6 49)<br />
(23 1 17 33 21 37)<br />
</pre><br />
<br />
Example in Haskell:<br />
<br />
<haskell><br />
λ> diff_select 6 49<br />
[23,1,17,33,21,37]<br />
</haskell><br />
<br />
[[99 questions/Solutions/24 | Solutions]]<br />
<br />
<br />
== Problem 25 ==<br />
<br />
Generate a random permutation of the elements of a list.<br />
<br />
Example:<br />
<br />
<pre><br />
* (rnd-permu '(a b c d e f))<br />
(B A D C E F)<br />
</pre><br />
<br />
Example in Haskell:<br />
<br />
<haskell><br />
λ> rnd_permu "abcdef"<br />
"badcef"<br />
</haskell><br />
<br />
[[99 questions/Solutions/25 | Solutions]]<br />
<br />
<br />
== Problem 26 ==<br />
<br />
(**) Generate the combinations of K distinct objects chosen from the N elements of a list<br />
<br />
In how many ways can a committee of 3 be chosen from a group of 12 people? We all know that there are C(12,3) = 220 possibilities (C(N,K) denotes the<br />
well-known binomial coefficients). For pure mathematicians, this result may be great. But we want to really generate all the possibilities in a list.<br />
<br />
Example:<br />
<br />
<pre><br />
* (combinations 3 '(a b c d e f))<br />
((A B C) (A B D) (A B E) ... )<br />
</pre><br />
<br />
Example in Haskell:<br />
<br />
<haskell><br />
λ> combinations 3 "abcdef"<br />
["abc","abd","abe",...]<br />
</haskell><br />
<br />
[[99 questions/Solutions/26 | Solutions]]<br />
<br />
<br />
== Problem 27 ==<br />
<br />
Group the elements of a set into disjoint subsets.<br />
<br />
a) In how many ways can a group of 9 people work in 3 disjoint subgroups of 2, 3 and 4 persons? Write a function that generates all the possibilities and returns them in a list.<br />
<br />
Example:<br />
<br />
<pre><br />
* (group3 '(aldo beat carla david evi flip gary hugo ida))<br />
( ( (ALDO BEAT) (CARLA DAVID EVI) (FLIP GARY HUGO IDA) )<br />
... )<br />
</pre><br />
<br />
b) Generalize the above predicate in a way that we can specify a list of group sizes and the predicate will return a list of groups.<br />
<br />
Example:<br />
<br />
<pre><br />
* (group '(aldo beat carla david evi flip gary hugo ida) '(2 2 5))<br />
( ( (ALDO BEAT) (CARLA DAVID) (EVI FLIP GARY HUGO IDA) )<br />
... )<br />
</pre><br />
<br />
Note that we do not want permutations of the group members; i.e. ((ALDO BEAT) ...) is the same solution as ((BEAT ALDO) ...). However, we make a difference between ((ALDO BEAT) (CARLA DAVID) ...) and ((CARLA DAVID) (ALDO BEAT) ...).<br />
<br />
You may find more about this combinatorial problem in a good book on discrete mathematics under the term "multinomial coefficients".<br />
<br />
Example in Haskell:<br />
<br />
<haskell><br />
λ> group [2,3,4] ["aldo","beat","carla","david","evi","flip","gary","hugo","ida"]<br />
[[["aldo","beat"],["carla","david","evi"],["flip","gary","hugo","ida"]],...]<br />
(altogether 1260 solutions)<br />
<br />
λ> group [2,2,5] ["aldo","beat","carla","david","evi","flip","gary","hugo","ida"]<br />
[[["aldo","beat"],["carla","david"],["evi","flip","gary","hugo","ida"]],...]<br />
(altogether 756 solutions)<br />
</haskell><br />
<br />
[[99 questions/Solutions/27 | Solutions]]<br />
<br />
<br />
<br />
== Problem 28 ==<br />
<br />
Sorting a list of lists according to length of sublists<br />
<br />
a) We suppose that a list contains elements that are lists themselves. The objective is to sort the elements of this list according to their length. E.g. short lists first, longer lists later, or vice versa.<br />
<br />
Example:<br />
<br />
<pre><br />
* (lsort '((a b c) (d e) (f g h) (d e) (i j k l) (m n) (o)))<br />
((O) (D E) (D E) (M N) (A B C) (F G H) (I J K L))<br />
</pre><br />
<br />
Example in Haskell:<br />
<br />
<haskell><br />
λ> lsort ["abc","de","fgh","de","ijkl","mn","o"]<br />
["o","de","de","mn","abc","fgh","ijkl"]<br />
</haskell><br />
<br />
b) Again, we suppose that a list contains elements that are lists themselves. But this time the objective is to sort the elements of this list according to their <b>length frequency</b>; i.e., in the default, where sorting is done ascendingly, lists with rare lengths are placed first, others with a more frequent length come later.<br />
<br />
Example:<br />
<br />
<pre><br />
* (lfsort '((a b c) (d e) (f g h) (d e) (i j k l) (m n) (o)))<br />
((i j k l) (o) (a b c) (f g h) (d e) (d e) (m n))<br />
</pre><br />
<br />
Example in Haskell:<br />
<br />
<haskell><br />
λ> lfsort ["abc", "de", "fgh", "de", "ijkl", "mn", "o"]<br />
["ijkl","o","abc","fgh","de","de","mn"]<br />
</haskell><br />
<br />
[[99 questions/Solutions/28 | Solutions]]<br />
<br />
<br />
[[Category:Tutorials]]</div>Wizzuphttps://wiki.haskell.org/index.php?title=99_questions/11_to_20&diff=6275399 questions/11 to 202019-02-08T08:38:09Z<p>Wizzup: unify ghci prompts</p>
<hr />
<div>__NOTOC__<br />
<br />
This is part of [[H-99:_Ninety-Nine_Haskell_Problems|Ninety-Nine Haskell Problems]], based on [https://prof.ti.bfh.ch/hew1/informatik3/prolog/p-99/ Ninety-Nine Prolog Problems] and [http://www.ic.unicamp.br/~meidanis/courses/mc336/2006s2/funcional/L-99_Ninety-Nine_Lisp_Problems.html Ninety-Nine Lisp Problems].<br />
<br />
== Problem 11 ==<br />
<br />
(*) Modified run-length encoding.<br />
<br />
Modify the result of problem 10 in such a way that if an element has no duplicates it is simply copied into the result list. Only elements with duplicates are transferred as (N E) lists.<br />
<br />
Example:<br />
<br />
<pre><br />
* (encode-modified '(a a a a b c c a a d e e e e))<br />
((4 A) B (2 C) (2 A) D (4 E))<br />
</pre><br />
<br />
Example in Haskell:<br />
<br />
<haskell><br />
λ> encodeModified "aaaabccaadeeee"<br />
[Multiple 4 'a',Single 'b',Multiple 2 'c',<br />
Multiple 2 'a',Single 'd',Multiple 4 'e']<br />
</haskell><br />
<br />
[[99 questions/Solutions/11 | Solutions]]<br />
<br />
== Problem 12 ==<br />
<br />
(**) Decode a run-length encoded list.<br />
<br />
Given a run-length code list generated as specified in problem 11. Construct its uncompressed version.<br />
<br />
Example in Haskell:<br />
<br />
<haskell><br />
λ> decodeModified <br />
[Multiple 4 'a',Single 'b',Multiple 2 'c',<br />
Multiple 2 'a',Single 'd',Multiple 4 'e']<br />
"aaaabccaadeeee"<br />
</haskell><br />
<br />
[[99 questions/Solutions/12 | Solutions]]<br />
<br />
== Problem 13 ==<br />
<br />
(**) Run-length encoding of a list (direct solution). <br />
<br />
Implement the so-called run-length encoding data compression method directly. I.e. don't explicitly create the sublists containing the duplicates, as in problem 9, but only count them. As in problem P11, simplify the result list by replacing the singleton lists (1 X) by X.<br />
<br />
Example:<br />
<br />
<pre><br />
* (encode-direct '(a a a a b c c a a d e e e e))<br />
((4 A) B (2 C) (2 A) D (4 E))<br />
</pre><br />
<br />
Example in Haskell:<br />
<br />
<haskell><br />
λ> encodeDirect "aaaabccaadeeee"<br />
[Multiple 4 'a',Single 'b',Multiple 2 'c',<br />
Multiple 2 'a',Single 'd',Multiple 4 'e']<br />
</haskell><br />
<br />
[[99 questions/Solutions/13 | Solutions]]<br />
<br />
== Problem 14 ==<br />
<br />
(*) Duplicate the elements of a list.<br />
<br />
Example:<br />
<br />
<pre><br />
* (dupli '(a b c c d))<br />
(A A B B C C C C D D)<br />
</pre><br />
<br />
Example in Haskell:<br />
<br />
<haskell><br />
λ> dupli [1, 2, 3]<br />
[1,1,2,2,3,3]<br />
</haskell><br />
<br />
[[99 questions/Solutions/14 | Solutions]]<br />
<br />
<br />
== Problem 15 ==<br />
<br />
(**) Replicate the elements of a list a given number of times.<br />
<br />
Example:<br />
<br />
<pre><br />
* (repli '(a b c) 3)<br />
(A A A B B B C C C)<br />
</pre><br />
<br />
Example in Haskell:<br />
<br />
<haskell><br />
λ> repli "abc" 3<br />
"aaabbbccc"<br />
</haskell><br />
<br />
[[99 questions/Solutions/15 | Solutions]]<br />
<br />
<br />
== Problem 16 ==<br />
<br />
(**) Drop every N'th element from a list.<br />
<br />
Example:<br />
<br />
<pre><br />
* (drop '(a b c d e f g h i k) 3)<br />
(A B D E G H K)<br />
</pre><br />
<br />
Example in Haskell:<br />
<br />
<haskell><br />
λ> dropEvery "abcdefghik" 3<br />
"abdeghk"<br />
</haskell><br />
<br />
[[99 questions/Solutions/16 | Solutions]]<br />
<br />
<br />
== Problem 17 ==<br />
<br />
(*) Split a list into two parts; the length of the first part is given.<br />
<br />
Do not use any predefined predicates.<br />
<br />
Example:<br />
<br />
<pre><br />
* (split '(a b c d e f g h i k) 3)<br />
( (A B C) (D E F G H I K))<br />
</pre><br />
<br />
Example in Haskell:<br />
<br />
<haskell><br />
λ> split "abcdefghik" 3<br />
("abc", "defghik")<br />
</haskell><br />
<br />
[[99 questions/Solutions/17 | Solutions]]<br />
<br />
<br />
== Problem 18 ==<br />
<br />
(**) Extract a slice from a list.<br />
<br />
Given two indices, i and k, the slice is the list containing the elements between the i'th and k'th element of the original list (both limits included). Start counting the elements with 1.<br />
<br />
Example:<br />
<br />
<pre><br />
* (slice '(a b c d e f g h i k) 3 7)<br />
(C D E F G)<br />
</pre><br />
<br />
Example in Haskell:<br />
<br />
<haskell><br />
λ> slice ['a','b','c','d','e','f','g','h','i','k'] 3 7<br />
"cdefg"<br />
</haskell><br />
<br />
[[99 questions/Solutions/18 | Solutions]]<br />
<br />
<br />
== Problem 19 ==<br />
<br />
(**) Rotate a list N places to the left.<br />
<br />
Hint: Use the predefined functions length and (++).<br />
<br />
Examples:<br />
<br />
<pre><br />
* (rotate '(a b c d e f g h) 3)<br />
(D E F G H A B C)<br />
<br />
* (rotate '(a b c d e f g h) -2)<br />
(G H A B C D E F)<br />
</pre><br />
<br />
Examples in Haskell:<br />
<br />
<haskell><br />
λ> rotate ['a','b','c','d','e','f','g','h'] 3<br />
"defghabc"<br />
<br />
λ> rotate ['a','b','c','d','e','f','g','h'] (-2)<br />
"ghabcdef"<br />
</haskell><br />
<br />
[[99 questions/Solutions/19 | Solutions]]<br />
<br />
<br />
== Problem 20 ==<br />
<br />
(*) Remove the K'th element from a list.<br />
<br />
Example in Prolog:<br />
<br />
<pre><br />
?- remove_at(X,[a,b,c,d],2,R).<br />
X = b<br />
R = [a,c,d]<br />
</pre><br />
<br />
Example in Lisp:<br />
<br />
<pre><br />
* (remove-at '(a b c d) 2)<br />
(A C D)<br />
</pre><br />
<br />
(Note that this only returns the residue list, while the Prolog version also returns the deleted element.)<br />
<br />
Example in Haskell:<br />
<br />
<haskell><br />
λ> removeAt 2 "abcd"<br />
('b',"acd")<br />
</haskell><br />
<br />
[[99 questions/Solutions/20 | Solutions]]<br />
<br />
<br />
[[Category:Tutorials]]</div>Wizzuphttps://wiki.haskell.org/index.php?title=99_questions/1_to_10&diff=6275299 questions/1 to 102019-02-08T08:31:40Z<p>Wizzup: unify `prelude` and `main` ghci prompts</p>
<hr />
<div>__NOTOC__<br />
<br />
This is part of [[H-99:_Ninety-Nine_Haskell_Problems|Ninety-Nine Haskell Problems]], based on [https://sites.google.com/site/prologsite/prolog-problems Ninety-Nine Prolog Problems] and [http://www.ic.unicamp.br/~meidanis/courses/mc336/2006s2/funcional/L-99_Ninety-Nine_Lisp_Problems.html Ninety-Nine Lisp Problems].<br />
<br />
== Problem 1 ==<br />
<br />
(*) Find the last element of a list.<br />
<br />
(Note that the Lisp transcription of this problem is incorrect.)<br />
<br />
Example in Haskell:<br />
<br />
<haskell><br />
λ> myLast [1,2,3,4]<br />
4<br />
λ> myLast ['x','y','z']<br />
'z'<br />
</haskell><br />
<br />
[[99 questions/Solutions/1 | Solutions]]<br />
<br />
<br />
== Problem 2 ==<br />
<br />
(*) Find the last but one element of a list.<br />
<br />
(Note that the Lisp transcription of this problem is incorrect.)<br />
<br />
Example in Haskell:<br />
<br />
<haskell><br />
λ> myButLast [1,2,3,4]<br />
3<br />
λ> myButLast ['a'..'z']<br />
'y'<br />
</haskell><br />
<br />
[[99 questions/Solutions/2 | Solutions]]<br />
<br />
<br />
== Problem 3 ==<br />
<br />
(*) Find the K'th element of a list. The first element in the list is number 1.<br />
<br />
Example:<br />
<br />
<pre><br />
* (element-at '(a b c d e) 3)<br />
c<br />
</pre><br />
<br />
Example in Haskell:<br />
<br />
<haskell><br />
λ> elementAt [1,2,3] 2<br />
2<br />
λ> elementAt "haskell" 5<br />
'e'<br />
</haskell><br />
<br />
[[99 questions/Solutions/3 | Solutions]]<br />
<br />
<br />
== Problem 4 ==<br />
<br />
(*) Find the number of elements of a list.<br />
<br />
Example in Haskell:<br />
<br />
<haskell><br />
λ> myLength [123, 456, 789]<br />
3<br />
λ> myLength "Hello, world!"<br />
13<br />
</haskell><br />
<br />
[[99 questions/Solutions/4 | Solutions]]<br />
<br />
<br />
== Problem 5 ==<br />
<br />
(*) Reverse a list.<br />
<br />
Example in Haskell:<br />
<br />
<haskell><br />
λ> myReverse "A man, a plan, a canal, panama!"<br />
"!amanap ,lanac a ,nalp a ,nam A"<br />
λ> myReverse [1,2,3,4]<br />
[4,3,2,1]<br />
</haskell><br />
<br />
[[99 questions/Solutions/5 | Solutions]]<br />
<br />
<br />
== Problem 6 ==<br />
<br />
(*) Find out whether a list is a palindrome. A palindrome can be read forward or backward; e.g. (x a m a x).<br />
<br />
Example in Haskell:<br />
<br />
<haskell><br />
λ> isPalindrome [1,2,3]<br />
False<br />
λ> isPalindrome "madamimadam"<br />
True<br />
λ> isPalindrome [1,2,4,8,16,8,4,2,1]<br />
True<br />
</haskell><br />
<br />
[[99 questions/Solutions/6 | Solutions]]<br />
<br />
<br />
== Problem 7 ==<br />
<br />
(**) Flatten a nested list structure.<br />
<br />
Transform a list, possibly holding lists as elements into a `flat' list by replacing each list with its elements (recursively).<br />
<br />
Example:<br />
<br />
<pre><br />
* (my-flatten '(a (b (c d) e)))<br />
(A B C D E)<br />
</pre><br />
<br />
Example in Haskell:<br />
<br />
We have to define a new data type, because lists in Haskell are homogeneous. <br />
<haskell><br />
data NestedList a = Elem a | List [NestedList a]<br />
</haskell><br />
<br />
<haskell><br />
λ> flatten (Elem 5)<br />
[5]<br />
λ> flatten (List [Elem 1, List [Elem 2, List [Elem 3, Elem 4], Elem 5]])<br />
[1,2,3,4,5]<br />
λ> flatten (List [])<br />
[]<br />
</haskell><br />
<br />
<br />
<br />
[[99 questions/Solutions/7 | Solutions]]<br />
<br />
== Problem 8 ==<br />
<br />
(**) Eliminate consecutive duplicates of list elements.<br />
<br />
If a list contains repeated elements they should be replaced with a single copy of the element. The order of the elements should not be changed.<br />
<br />
Example:<br />
<br />
<pre><br />
* (compress '(a a a a b c c a a d e e e e))<br />
(A B C A D E)<br />
</pre><br />
<br />
Example in Haskell:<br />
<br />
<haskell><br />
> compress "aaaabccaadeeee"<br />
"abcade"<br />
</haskell><br />
<br />
[[99 questions/Solutions/8 | Solutions]]<br />
<br />
== Problem 9 ==<br />
<br />
(**) Pack consecutive duplicates of list elements into sublists.<br />
If a list contains repeated elements they should be placed in separate sublists.<br />
<br />
Example:<br />
<br />
<pre><br />
* (pack '(a a a a b c c a a d e e e e))<br />
((A A A A) (B) (C C) (A A) (D) (E E E E))<br />
</pre><br />
<br />
Example in Haskell:<br />
<br />
<haskell><br />
λ> pack ['a', 'a', 'a', 'a', 'b', 'c', 'c', 'a', <br />
'a', 'd', 'e', 'e', 'e', 'e']<br />
["aaaa","b","cc","aa","d","eeee"]<br />
</haskell><br />
<br />
[[99 questions/Solutions/9 | Solutions]]<br />
<br />
== Problem 10 ==<br />
<br />
(*) Run-length encoding of a list.<br />
Use the result of problem P09 to implement the so-called run-length encoding data compression method. Consecutive duplicates of elements are encoded as lists (N E) where N is the number of duplicates of the element E.<br />
<br />
Example:<br />
<pre><br />
* (encode '(a a a a b c c a a d e e e e))<br />
((4 A) (1 B) (2 C) (2 A) (1 D)(4 E))<br />
</pre><br />
<br />
Example in Haskell:<br />
<haskell><br />
λ> encode "aaaabccaadeeee"<br />
[(4,'a'),(1,'b'),(2,'c'),(2,'a'),(1,'d'),(4,'e')]<br />
</haskell><br />
<br />
[[99 questions/Solutions/10 | Solutions]]<br />
<br />
<br />
[[Category:Tutorials]]</div>Wizzuphttps://wiki.haskell.org/index.php?title=Talk:99_questions/1_to_10&diff=62751Talk:99 questions/1 to 102019-02-08T07:41:45Z<p>Wizzup: </p>
<hr />
<div>==Bad format==<br />
<br />
The format of this page is awful. I'm collecting the problem descriptions, but having to be very careful not to look at the solutions.<br />
<br />
The function signature and description of what it is to do should be given. The solutions should be on some separate page.<br />
<br />
: +1, especially the solutions on separate page. [[User:Oligomous|Oligomous]] 18:15, 8 December 2009 (UTC)<br />
: +1, agreed. Having visible solutions on this page really takes the fun out of it. I think I will start moving the solutions to subpages of [[99 questions/Solutions]], after solving them myself of course :-) [[User:Wapcaplet|Wapcaplet]] 15:05, 13 July 2010 (UTC)<br />
<br />
What is the meaning of star (*) in front of problem description?<br />
: Is it difficulty level indication? [[User:Wizzup|Wizzup]] ([[User talk:Wizzup|talk]]) 07:41, 8 February 2019 (UTC)<br />
<br />
Should we remove Lisp example?<br />
: I think Lisp example is somewhat out-of-context. [[User:Wizzup|Wizzup]] ([[User talk:Wizzup|talk]]) 07:41, 8 February 2019 (UTC)<br />
<br />
==Does the problem 1 example need correction?==<br />
<br />
The problem refers us to <hask>last</hask> as a <hask>Prelude</hask> function providing the same functionality. However, <hask>last</hask> has type <hask>[a] -> a</hask> which differs from the Lisp example's type <hask>[a] -> [a]</hask>. Should we revise the example or should we rephrase the reference to <hask>last</hask> to highlight the difference?<br />
<br />
[[User:Chrycheng|Chrycheng]] 12:02, 12 September 2007 (UTC)<br />
<br />
I think the answer to problem 6 is kind of "cheating". I think something like this would be a nice alternate solutions:<br />
<br />
<haskell><br />
isPalindrome :: Eq (a) => [a] -> Bool<br />
isPalindrome [] = True<br />
isPalindrome [x] = True<br />
isPalindrome (x:xs) = x == last xs && isPalindrome (init xs)<br />
</haskell><br />
<br />
[[User:Michael|Michael]] 16:40, 17 January 2008 (UTC)<br />
<br />
== Change Questions+Answers to be curry friendly ==<br />
<br />
I am not a long time Haskell user but it seems like many of these questions have not yet been reworded for Haskell. An example would be problem 3. The Haskell version should have the number of the element that you are getting then the list not the other way around.<br />
<br />
Example#1<br />
<br />
== Problem 3 ==<br />
<br />
(*) Find the K'th element of a list. The first element in the list is number 1.<br />
<br />
Example:<br />
<br />
<pre><br />
* (element-at '(a b c d e) 3)<br />
c<br />
</pre><br />
<br />
Example in Haskell:<br />
<br />
<haskell><br />
Prelude> elementAt 2 [1,2,3]<br />
2<br />
Prelude> elementAt 5 "haskell"<br />
'e'<br />
</haskell></div>Wizzuphttps://wiki.haskell.org/index.php?title=Let_vs._Where&diff=62737Let vs. Where2019-01-26T07:41:14Z<p>Wizzup: /* Advantages of where */</p>
<hr />
<div>Haskell programmers often wonder whether to use <hask>let</hask> or <hask>where</hask>.<br />
This seems to be only a matter of taste in the sense of "[[Declaration vs. expression style]]", however there is more to it.<br />
<br />
It is important to know that <hask>let ... in ...</hask> is an expression, that is, it can be written wherever expressions are allowed. In contrast, <hask>where</hask> is bound to a surrounding syntactic construct, like the [[pattern matching]] line of a function definition.<br />
<br />
== Advantages of let ==<br />
<br />
Suppose you have the function<br />
<haskell><br />
f :: s -> (a,s)<br />
f x = y<br />
where y = ... x ...<br />
</haskell><br />
and later you decide to put this into the <hask>Control.Monad.State</hask> monad.<br />
However, transforming to<br />
<haskell><br />
f :: State s a<br />
f = State $ \x -> y<br />
where y = ... x ...<br />
</haskell><br />
will not work, because <hask>where</hask> refers to the pattern matching <hask> f = </hask>,<br />
where no <hask>x</hask> is in scope.<br />
<br />
In contrast, if you had started with <hask>let</hask>, then you wouldn't have trouble.<br />
<haskell><br />
f :: s -> (a,s)<br />
f x =<br />
let y = ... x ...<br />
in y<br />
</haskell><br />
This is easily transformed to:<br />
<haskell><br />
f :: State s a<br />
f = State $ \x -><br />
let y = ... x ...<br />
in y<br />
</haskell><br />
<br />
== Advantages of where ==<br />
<br />
Because "where" blocks are bound to a syntactic construct, they can be used to share bindings between parts of a function that are not syntactically expressions. For example:<br />
<br />
<haskell><br />
f x<br />
| cond1 x = a<br />
| cond2 x = g a<br />
| otherwise = f (h x a)<br />
where<br />
a = w x<br />
</haskell><br />
<br />
In expression style, you might use an explicit <hask>case</hask>:<br />
<br />
<haskell><br />
f x<br />
= let a = w x<br />
in case () of<br />
_ | cond1 x -> a<br />
| cond2 x -> g a<br />
| otherwise -> f (h x a)<br />
</haskell><br />
<br />
or a [[Case|functional equivalent]]:<br />
<br />
<haskell><br />
f x =<br />
let a = w x<br />
in select (f (h x a))<br />
[(cond1 x, a),<br />
(cond2 x, g a)]<br />
</haskell><br />
<br />
or a series of if-then-else expressions:<br />
<br />
<haskell><br />
f x<br />
= let a = w x<br />
in if cond1 x<br />
then a<br />
else if cond2 x<br />
then g a<br />
else f (h x a)<br />
</haskell><br />
<br />
These alternatives are arguably less readable and hide the structure of the function more than simply using <hask>where</hask>.<br />
<br />
== Lambda Lifting ==<br />
<br />
One other approach to consider is that let or where can often be implemented using [[lambda lifting]] and [[let floating]], incurring at least the cost of introducing a new name. The above example:<br />
<br />
<haskell><br />
f x<br />
| cond1 x = a<br />
| cond2 x = g a<br />
| otherwise = f (h x a)<br />
where<br />
a = w x<br />
</haskell><br />
<br />
could be implemented as:<br />
<br />
<haskell><br />
f x = f' (w x) x<br />
<br />
f' a x<br />
| cond1 x = a<br />
| cond2 x = g a<br />
| otherwise = f (h x a)<br />
</haskell><br />
<br />
The auxiliary definition can either be a top-level binding, or included in f using <hask>let</hask> or <hask>where</hask>.<br />
<br />
== Problems with where ==<br />
<br />
If you run both<br />
<br />
<haskell><br />
fib = (map fib' [0 ..] !!)<br />
where<br />
fib' 0 = 0<br />
fib' 1 = 1<br />
fib' n = fib (n - 1) + fib (n - 2)<br />
</haskell><br />
<br />
and<br />
<br />
<haskell><br />
fib x = map fib' [0 ..] !! x<br />
where<br />
fib' 0 = 0<br />
fib' 1 = 1<br />
fib' n = fib (n - 1) + fib (n - 2)<br />
</haskell><br />
<br />
you will notice that the second one runs considerably slower than the first. You may wonder why simply adding an explicit argument to <hask>fib</hask> (known as [[eta expansion]]) degrades performance so dramatically.<br />
<br />
You might see the reason better if you rewrote this code using <hask>let</hask>.<br />
<br />
Compare<br />
<br />
<haskell><br />
fib =<br />
let fib' 0 = 0<br />
fib' 1 = 1<br />
fib' n = fib (n - 1) + fib (n - 2)<br />
in (map fib' [0 ..] !!)<br />
</haskell><br />
<br />
and<br />
<br />
<haskell><br />
fib x =<br />
let fib' 0 = 0<br />
fib' 1 = 1<br />
fib' n = fib (n - 1) + fib (n - 2)<br />
in map fib' [0 ..] !! x<br />
</haskell><br />
<br />
In the second case, <hask>fib'</hask> is redefined for every argument <hask>x</hask>. The compiler cannot know whether you intended this -- while it increases time complexity it may reduce space complexity. Thus it will not float the definition out from under the binding of x.<br><br><br />
<br />
In contrast, in the first function, <hask>fib'</hask> can be moved to the top level by the compiler. The <hask>where</hask> clause hid this structure<br />
and made the application to <hask>x</hask> look like a plain eta expansion, which it is not.<br />
<br />
* Haskell-Cafe on [http://www.haskell.org/pipermail/haskell-cafe/2010-October/084538.html Eta-expansion destroys memoization?]<br />
<br />
<br />
[[Category:Style]]<br />
[[Category:Syntax]]</div>Wizzuphttps://wiki.haskell.org/index.php?title=Online_judges&diff=62267Online judges2017-12-31T12:49:08Z<p>Wizzup: add riddles.io</p>
<hr />
<div>Among many [https://en.wikipedia.org/wiki/Online_judge Online judges] and competitive coding sites there are some that support Haskell, listed in following table.<br />
<br />
{| class="wikitable"<br />
|-<br />
! Site !! GHC version<br />
|-<br />
| [https://www.codingame.com CodinGame ] || [https://www.codingame.com/faq 8.2.1]<br />
|-<br />
| [https://www.hackerrank.com HackerRank ] || [https://www.hackerrank.com/environment 8.0.2]<br />
|-<br />
| [https://www.codechef.com CodeChef ] || [https://www.codechef.com/ide 8.0.1]<br />
|-<br />
| [https://open.kattis.com Kattis ] || [https://open.kattis.com/help/haskell 7.10.3]<br />
|-<br />
| [https://www.riddles.io Riddles.io ] || [https://playground.riddles.io/competitions/light-riders/how-to-play 7.10.3]<br />
|-<br />
| [https://www.codewars.com CodeWars ] || 7.10.3<br />
|-<br />
| [http://codeforces.com CodeForces ] || 7.8.3<br />
|-<br />
| [https://www.hackerearth.com HackerEarth ] || [https://www.hackerearth.com/docs/wiki/developers/judge 7.6.3]<br />
|-<br />
| [https://codefights.com CodeFights ] || 7.6.3<br />
|-<br />
| [http://www.devdraft.com devdraft ] || 7.6<br />
|-<br />
| [http://exercism.io exercism.io ] || Multiple version (using stack)<br />
|-<br />
| [http://codeabbey.com codeabbey ] || (unknown)<br />
|-<br />
| [http://www.edufyme.com edufyme ] || (unknown)<br />
|-<br />
<!-- | [https://www.codeeval.com CodeEval ] || Broken --><br />
|-<br />
<!-- | [http://theaigames.com TheAIGame ] || 7.10 (defunct) --><br />
|}</div>Wizzuphttps://wiki.haskell.org/index.php?title=Talk:Default_values_in_records&diff=62260Talk:Default values in records2017-12-26T07:16:24Z<p>Wizzup: Created page with "What about [https://hackage.haskell.org/package/data-default Data.Default], does it related to this topic? ~~~~"</p>
<hr />
<div>What about [https://hackage.haskell.org/package/data-default Data.Default], does it related to this topic? [[User:Wizzup|Wizzup]] ([[User talk:Wizzup|talk]]) 07:16, 26 December 2017 (UTC)</div>Wizzuphttps://wiki.haskell.org/index.php?title=Online_judges&diff=62253Online judges2017-12-18T05:30:00Z<p>Wizzup: </p>
<hr />
<div>Among many [https://en.wikipedia.org/wiki/Online_judge Online judges] and competitive coding sites there are some that support Haskell, listed in following table.<br />
<br />
{| class="wikitable"<br />
|-<br />
! Site !! GHC version<br />
|-<br />
| [https://www.codingame.com CodinGame ] || [https://www.codingame.com/faq 8.2.1]<br />
|-<br />
| [https://www.hackerrank.com HackerRank ] || [https://www.hackerrank.com/environment 8.0.2]<br />
|-<br />
| [https://www.codechef.com CodeChef ] || [https://www.codechef.com/ide 8.0.1]<br />
|-<br />
| [https://open.kattis.com Kattis ] || [https://open.kattis.com/help/haskell 7.10.3]<br />
|-<br />
| [https://www.codewars.com CodeWars ] || 7.10.3<br />
|-<br />
| [http://codeforces.com CodeForces ] || 7.8.3<br />
|-<br />
| [https://www.hackerearth.com HackerEarth ] || [https://www.hackerearth.com/docs/wiki/developers/judge 7.6.3]<br />
|-<br />
| [https://codefights.com CodeFights ] || 7.6.3<br />
|-<br />
| [http://www.devdraft.com devdraft ] || 7.6<br />
|-<br />
| [http://exercism.io exercism.io ] || Multiple version (using stack)<br />
|-<br />
| [http://codeabbey.com codeabbey ] || (unknown)<br />
|-<br />
| [http://www.edufyme.com edufyme ] || (unknown)<br />
|-<br />
<!-- | [https://www.codeeval.com CodeEval ] || Broken --><br />
|-<br />
<!-- | [http://theaigames.com TheAIGame ] || 7.10 (defunct) --><br />
|}</div>Wizzuphttps://wiki.haskell.org/index.php?title=Online_judges&diff=62252Online judges2017-12-18T05:26:22Z<p>Wizzup: </p>
<hr />
<div>Among many [https://en.wikipedia.org/wiki/Online_judge Online judges] and competitive coding sites there are some that support Haskell, listed in following table.<br />
<br />
{| class="wikitable"<br />
|-<br />
! Site !! GHC version<br />
|-<br />
| [https://www.codingame.com CodinGame ] || [https://www.codingame.com/faq 8.2.1]<br />
|-<br />
| [https://www.hackerrank.com HackerRank ] || [https://www.hackerrank.com/environment 8.0.2]<br />
|-<br />
| [https://open.kattis.com Kattis ] || [https://open.kattis.com/help/haskell 7.10.3]<br />
|-<br />
| [https://www.codewars.com CodeWars ] || 7.10.3<br />
|-<br />
| [http://codeforces.com CodeForces ] || 7.8.3<br />
|-<br />
| [https://www.hackerearth.com HackerEarth ] || [https://www.hackerearth.com/docs/wiki/developers/judge 7.6.3]<br />
|-<br />
| [https://codefights.com CodeFights ] || 7.6.3<br />
|-<br />
| [https://www.codechef.com CodeChef ] || 7.6.3<br />
|-<br />
| [http://www.devdraft.com devdraft ] || 7.6<br />
|-<br />
| [http://exercism.io exercism.io ] || Multiple version (using stack)<br />
|-<br />
| [http://codeabbey.com codeabbey ] || (unknown)<br />
|-<br />
| [http://www.edufyme.com edufyme ] || (unknown)<br />
|-<br />
<!-- | [https://www.codeeval.com CodeEval ] || Broken --><br />
|-<br />
<!-- | [http://theaigames.com TheAIGame ] || 7.10 (defunct) --><br />
|}</div>Wizzuphttps://wiki.haskell.org/index.php?title=Vim&diff=62251Vim2017-12-16T09:57:44Z<p>Wizzup: /* List of Plugins */ remove dead link</p>
<hr />
<div>[[Category:Development tools]] <br />
This page is intended for Haskell vim-users.<br />
<br />
= Indentation =<br />
<br />
The following setup from merijn @ #haskell ensures you use spaces not tabs for indentation for generally sane behaviour:<br />
<br />
<pre><br />
" Tab specific option<br />
set tabstop=8 "A tab is 8 spaces<br />
set expandtab "Always uses spaces instead of tabs<br />
set softtabstop=4 "Insert 4 spaces when tab is pressed<br />
set shiftwidth=4 "An indent is 4 spaces<br />
set shiftround "Round indent to nearest shiftwidth multiple<br />
</pre><br />
<br />
= Plugins =<br />
Put code in file <code>~/.vim/plugin/Haskell.vim</code>, or in multiple files in that directory. <br />
<br />
== Module Sections ==<br />
The following code prompts for a name, and places a section with that name at current position, when key sequence "--s":<br />
<pre><br />
let s:width = 80<br />
<br />
function! HaskellModuleSection(...)<br />
let name = 0 < a:0 ? a:1 : inputdialog("Section name: ")<br />
<br />
return repeat('-', s:width) . "\n"<br />
\ . "-- " . name . "\n"<br />
\ . "\n"<br />
<br />
endfunction<br />
<br />
nmap <silent> --s "=HaskellModuleSection()<CR>gp<br />
</pre><br />
Like so:<br />
<haskell><br />
<br />
--------------------------------------------------------------------------------<br />
-- my section<br />
<br />
</haskell><br />
<br />
<br />
== Module Headers ==<br />
The following code prompts for module name, a note, a description of module, and places a module comment at top, when key sequence "--h":<br />
<pre><br />
let s:width = 80<br />
<br />
<br />
function! HaskellModuleHeader(...)<br />
let name = 0 < a:0 ? a:1 : inputdialog("Module: ")<br />
let note = 1 < a:0 ? a:2 : inputdialog("Note: ")<br />
let description = 2 < a:0 ? a:3 : inputdialog("Describe this module: ")<br />
<br />
return repeat('-', s:width) . "\n" <br />
\ . "-- | \n" <br />
\ . "-- Module : " . name . "\n"<br />
\ . "-- Note : " . note . "\n"<br />
\ . "-- \n"<br />
\ . "-- " . description . "\n"<br />
\ . "-- \n"<br />
\ . repeat('-', s:width) . "\n"<br />
\ . "\n"<br />
<br />
endfunction<br />
<br />
<br />
nmap <silent> --h "=HaskellModuleHeader()<CR>:0put =<CR><br />
</pre><br />
like so:<br />
<haskell><br />
--------------------------------------------------------------------------------<br />
-- | <br />
-- Module : MyModule<br />
-- Note : This is a preview<br />
-- <br />
-- This is an empty module, to show the headercomment produced. <br />
-- <br />
--------------------------------------------------------------------------------<br />
<br />
<br />
</haskell><br />
<br />
== List of Plugins ==<br />
<br />
* [https://github.com/bitc/vim-hdevtools Hdevtools] taken from the github page:<br />
<blockquote><br />
hdevtools is a command line program powered by the GHC API, that provides services for Haskell development. hdevtools works by running a persistent process in the background, so that your Haskell modules remain in memory, instead of having to reload everything each time you change only one file. This is just like :reload in GHCi - with hdevtools you get the speed of GHCi as well as tight integration with your editor.<br />
<br />
This is the Vim plugin that integrates Vim with hdevtools.<br />
</blockquote><br />
<br />
<br />
*[https://github.com/lukerandall/haskellmode-vim Haskellmode-vim] from the github:<br />
<blockquote><br />
The Haskell mode plugins provide advanced support for Haskell development<br />
using GHC/GHCi on Windows and Unix-like systems. The functionality is<br />
based on Haddock-generated library indices, on GHCi's interactive<br />
commands, or on simply activating (some of) Vim's built-in program editing<br />
support in Haskell-relevant fashion. These plugins live side-by-side with<br />
the pre-defined |syntax-highlighting| support for |haskell| sources, and<br />
any other Haskell-related plugins you might want to install (see<br />
|haskellmode-resources|).<br />
<br />
The Haskell mode plugins consist of three filetype plugins (haskell.vim,<br />
haskell_doc.vim, haskell_hpaste.vim), which by Vim's |filetype| detection<br />
mechanism will be auto-loaded whenever files with the extension '.hs' are<br />
opened, and one compiler plugin (ghc.vim) which you will need to load from<br />
your vimrc file (see |haskellmode-settings|).<br />
</blockquote><br />
<br />
* [https://github.com/eagletmt/ghcmod-vim Ghcmod-vim] from the github Page:<br />
<blockquote><br />
Displaying the type of sub-expressions (ghc-mod type)<br />
Displaying error/warning messages and their locations (ghc-mod check and ghc-mod lint)<br />
Displaying the expansion of splices (ghc-mod expand)<br />
Completions are supported by another plugin. See neco-ghc .<br />
</blockquote>.<br />
<br />
* [https://github.com/scrooloose/syntastic Syntastic] supports Haskell and several other languages. From the github<br />
<blockquote><br />
Syntastic is a syntax checking plugin that runs files through external syntax checkers and displays any resulting errors to the user. This can be done on demand, or automatically as files are saved. If syntax errors are detected, the user is notified and is happy because they didn't have to compile their code or execute their script to find them.<br />
<br />
At the time of this writing, syntax checking plugins exist for applescript, c, coffee, cpp, css, cucumber, cuda, docbk, erlang, eruby, fortran, gentoo_metadata, go, haml, haskell, html, javascript, json, less, lua, matlab, perl, php, puppet, python, rst, ruby, sass/scss, sh, tcl, tex, vala, xhtml, xml, xslt, yaml, zpt<br />
</blockquote><br />
<br />
* [https://github.com/ujihisa/neco-ghc Neco-ghc] power by ghcmod-vim for completion of pragma, modules, functions and more.<br />
<br />
<!-- * [http://blog.mno2.org/posts/2011-11-17-vim-plugins-for-haskell-programmers.html Addition list] with some missing here with screen shots of many of the above. --></div>Wizzuphttps://wiki.haskell.org/index.php?title=Programming_contests&diff=62250Programming contests2017-12-16T09:53:05Z<p>Wizzup: /* Online Judges */</p>
<hr />
<div>There are a number of online programming contests of interest to Haskell<br />
programmers. This page attempts to document and help coordinate the<br />
efforts of the Haskell community.<br />
<br />
== The ICFP Programming Contest ==<br />
<br />
A yearly contest run by the functional programming community, open to<br />
all comers. Haskell has been highly successful over the years, winning<br />
several times.<br />
<br />
* [[ICFP Programming Contest]]<br />
* [http://www.icfpcontest.org/ ICFP contest home]<br />
<br />
== Great Language Shootout ==<br />
<br />
A highly visible language performance contest.<br />
<br />
* [http://shootout.alioth.debian.org/gp4/benchmark.php?test=all&lang=all The Great Language Shootout]<br />
<br />
We have [[Great_language_shootout|a separate page]] to track the Haskell submissions and discuss improvements.<br />
<br />
== The Ruby Quiz ==<br />
<br />
Haskell implementations of the ruby quiz problems are collected here:<br />
<br />
* The [[Haskell Quiz]]<br />
<br />
== Online Judges ==<br />
<br />
* [[SPOJ|The Sphere Online Judge]] contest<br />
* [[Online_judges|List]] of judges platform that support Haskell<br />
<br />
== Project Euler ==<br />
<br />
"Project Euler is a series of challenging mathematical/computer programming problems that will require more than just mathematical insights to solve."<br />
<br />
* [http://projecteuler.net/ Project Euler]<br />
<br />
== International Obfuscated Haskell Code Contest ==<br />
<br />
The IOHCC has been held three times.<br />
<br />
* [[Obfuscation]]<br />
<br />
[[Category:Contests]]</div>Wizzuphttps://wiki.haskell.org/index.php?title=Online_judges&diff=62248Online judges2017-12-16T09:51:58Z<p>Wizzup: Wizzup moved page Online judge to Online judges</p>
<hr />
<div>Among many [https://en.wikipedia.org/wiki/Online_judge Online judges] and competitive coding sites there are some that support Haskell, listed in following table.<br />
<br />
{| class="wikitable"<br />
|-<br />
! Site !! GHC version<br />
|-<br />
| [https://www.codingame.com CodinGame ] || [https://www.codingame.com/faq 8.2.1]<br />
|-<br />
| [https://www.hackerrank.com HackerRank ] || [https://www.hackerrank.com/environment 8.0.2]<br />
|-<br />
| [https://open.kattis.com Kattis ] || [https://open.kattis.com/help/haskell 7.10.3]<br />
|-<br />
| [https://www.codewars.com CodeWars ] || 7.10.3<br />
|-<br />
| [http://codeforces.com CodeForces ] || 7.8.3<br />
|-<br />
| [https://www.hackerearth.com HackerEarth ] || [https://www.hackerearth.com/docs/wiki/developers/judge 7.6.3]<br />
|-<br />
| [https://codefights.com CodeFights ] || 7.6.3<br />
|-<br />
| [https://www.codechef.com CodeChef ] || 7.6.3<br />
|-<br />
| [http://www.devdraft.com devdraft ] || 7.6<br />
|-<br />
| [http://exercism.io exercism.io ] || (unknown, stack)<br />
|-<br />
| [http://codeabbey.com codeabbey ] || (unknown)<br />
|-<br />
| [http://www.edufyme.com edufyme ] || (unknown)<br />
|-<br />
<!-- | [https://www.codeeval.com CodeEval ] || Broken --><br />
|-<br />
<!-- | [http://theaigames.com TheAIGame ] || 7.10 (defunct) --><br />
|}</div>Wizzuphttps://wiki.haskell.org/index.php?title=Online_judge&diff=62249Online judge2017-12-16T09:51:58Z<p>Wizzup: Wizzup moved page Online judge to Online judges</p>
<hr />
<div>#REDIRECT [[Online judges]]</div>Wizzuphttps://wiki.haskell.org/index.php?title=Online_judges&diff=62247Online judges2017-12-16T07:40:06Z<p>Wizzup: </p>
<hr />
<div>Among many [https://en.wikipedia.org/wiki/Online_judge Online judges] and competitive coding sites there are some that support Haskell, listed in following table.<br />
<br />
{| class="wikitable"<br />
|-<br />
! Site !! GHC version<br />
|-<br />
| [https://www.codingame.com CodinGame ] || [https://www.codingame.com/faq 8.2.1]<br />
|-<br />
| [https://www.hackerrank.com HackerRank ] || [https://www.hackerrank.com/environment 8.0.2]<br />
|-<br />
| [https://open.kattis.com Kattis ] || [https://open.kattis.com/help/haskell 7.10.3]<br />
|-<br />
| [https://www.codewars.com CodeWars ] || 7.10.3<br />
|-<br />
| [http://codeforces.com CodeForces ] || 7.8.3<br />
|-<br />
| [https://www.hackerearth.com HackerEarth ] || [https://www.hackerearth.com/docs/wiki/developers/judge 7.6.3]<br />
|-<br />
| [https://codefights.com CodeFights ] || 7.6.3<br />
|-<br />
| [https://www.codechef.com CodeChef ] || 7.6.3<br />
|-<br />
| [http://www.devdraft.com devdraft ] || 7.6<br />
|-<br />
| [http://exercism.io exercism.io ] || (unknown, stack)<br />
|-<br />
| [http://codeabbey.com codeabbey ] || (unknown)<br />
|-<br />
| [http://www.edufyme.com edufyme ] || (unknown)<br />
|-<br />
<!-- | [https://www.codeeval.com CodeEval ] || Broken --><br />
|-<br />
<!-- | [http://theaigames.com TheAIGame ] || 7.10 (defunct) --><br />
|}</div>Wizzuphttps://wiki.haskell.org/index.php?title=Online_judges&diff=62246Online judges2017-12-16T07:20:02Z<p>Wizzup: </p>
<hr />
<div>Among many [https://en.wikipedia.org/wiki/Online_judge Online judges] and competitive coding sites there are some that support Haskell, listed in following table.<br />
<br />
{| class="wikitable"<br />
|-<br />
! Site !! GHC version<br />
|-<br />
| [https://www.codingame.com CodinGame ] || [https://www.codingame.com/faq 8.2.1]<br />
|-<br />
| [https://www.hackerrank.com HackerRank ] || [https://www.hackerrank.com/environment 8.0.2]<br />
|-<br />
| [https://open.kattis.com Kattis ] || [https://open.kattis.com/help/haskell 7.10.3]<br />
|-<br />
| [https://www.codewars.com CodeWars ] || 7.10.3<br />
|-<br />
| [http://codeforces.com CodeForces ] || 7.8.3<br />
|-<br />
| [https://codefights.com CodeFights ] || 7.6.3<br />
|-<br />
| [https://www.codechef.com CodeChef ] || 7.6.3<br />
|-<br />
| [https://www.hackerearth.com HackerEarth ] || 7.6.3<br />
|-<br />
| [http://www.devdraft.com devdraft ] || 7.6<br />
|-<br />
| [http://exercism.io exercism.io ] || (unknown, stack)<br />
|-<br />
| [http://codeabbey.com codeabbey ] || (unknown)<br />
|-<br />
| [http://www.edufyme.com edufyme ] || (unknown)<br />
|-<br />
<!-- | [https://www.codeeval.com CodeEval ] || Broken --><br />
|-<br />
<!-- | [http://theaigames.com TheAIGame ] || 7.10 (defunct) --><br />
|}</div>Wizzuphttps://wiki.haskell.org/index.php?title=Online_judges&diff=62245Online judges2017-12-16T07:18:06Z<p>Wizzup: </p>
<hr />
<div>Among many [https://en.wikipedia.org/wiki/Online_judge Online judges] and competitive coding sites there are some that support Haskell, listed in following table.<br />
<br />
{| class="wikitable"<br />
|-<br />
! Site !! GHC version<br />
|-<br />
| [https://www.codingame.com CodinGame ] || [https://www.codingame.com/faq 8.2.1]<br />
|-<br />
| [https://open.kattis.com Kattis ] || [https://open.kattis.com/help/haskell 7.10.3]<br />
|-<br />
| [https://www.codewars.com CodeWars ] || 7.10.3<br />
|-<br />
| [https://www.hackerrank.com HackerRank ] || 7.8.4<br />
|-<br />
| [http://codeforces.com CodeForces ] || 7.8.3<br />
|-<br />
| [https://codefights.com CodeFights ] || 7.6.3<br />
|-<br />
| [https://www.codechef.com CodeChef ] || 7.6.3<br />
|-<br />
| [https://www.hackerearth.com HackerEarth ] || 7.6.3<br />
|-<br />
| [http://www.devdraft.com devdraft ] || 7.6<br />
|-<br />
| [http://exercism.io exercism.io ] || (unknown, stack)<br />
|-<br />
| [http://codeabbey.com codeabbey ] || (unknown)<br />
|-<br />
| [http://www.edufyme.com edufyme ] || (unknown)<br />
|-<br />
<!-- | [https://www.codeeval.com CodeEval ] || Broken --><br />
|-<br />
<!-- | [http://theaigames.com TheAIGame ] || 7.10 (defunct) --><br />
|}</div>Wizzup