https://wiki.haskell.org/api.php?action=feedcontributions&user=Tschrijvers&feedformat=atomHaskellWiki - User contributions [en]2021-05-16T16:10:17ZUser contributionsMediaWiki 1.27.4https://wiki.haskell.org/index.php?title=User_groups&diff=59508User groups2015-03-10T09:02:15Z<p>Tschrijvers: </p>
<hr />
<div>[[Category:Community]]<br />
<br />
A range of Haskell User Groups are springing up all over.<br />
<br />
== Online communities ==<br />
* [http://www.reddit.com/r/haskell/ Haskell Reddit]<br />
* [http://stackoverflow.com/questions/tagged?tagnames=haskell Haskell on Stack Overflow]<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 />
===North America===<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://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 />
====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 />
;[https://groups.google.com/forum/?fromgroups#!forum/haskellers-montreal Montreal Haskell Users' Group].<br />
:Meets monthly.<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/nashkell Nashkell - Nashville Haskell Users Group] <br />
<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 />
===Europe===<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 />
==== 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 />
==== Netherlands ====<br />
<br />
;[http://dutchhug.nl/ Dutch HUG]<br />
:The Dutch HUG meets monthly in an informal setting.<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 />
==== Germany ====<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 />
;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])<br />
* '''Konstanz''': [[User:Thkoch|thkoch]]<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 />
==== 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 />
==== Iceland ====<br />
<br />
;[[Reykjavik Haskell User Group]] Iceland<br />
;[http://groups.google.com/group/haskell-is Currently recruiting members]<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 />
==== 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://ro-che.info/odhug Odessa Haskell User Group]<br />
:Regular informal meetups (approximately once a month) in a pub or cafe<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 />
==== 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 />
=== Israel ===<br />
<br />
;[[IsraelHaskell]] User Group<br />
:[http://article.gmane.org/gmane.comp.lang.haskell.cafe/28877 Are getting organised].<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 />
=== 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 />
===South America===<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 />
==== 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 />
===Asia===<br />
<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 />
;[http://www.starling-software.com/en/tsac.html Tokyo Society for the Application of Currying]<br />
<br />
;[http://www.meetup.com/HK-Functional-programming/ Hong Kong Functional Programming User Meetup Group]<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 />
== 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>Tschrijvershttps://wiki.haskell.org/index.php?title=Haskell_in_research&diff=59024Haskell in research2014-10-22T14:15:42Z<p>Tschrijvers: /* Research groups */</p>
<hr />
<div>Since its inception, Haskell development has been driven by programming<br />
language researchers. This page collects information about that community.<br />
<br />
==Research groups==<br />
<br />
*[http://www-i2.informatik.rwth-aachen.de/Forschung/FP/ Aachen]<br />
*[http://www-fp.cs.st-andrews.ac.uk/index.shtml St. Andrews]<br />
*[http://www.cs.bris.ac.uk/%7Eian/Functional/ Bristol]<br />
*[http://www.md.chalmers.se/Cs/Research/Functional/ Chalmers]<br />
*[http://www.ittc.ku.edu/research/view_lab.phtml?lab=CSDL Kansas]<br />
*[http://www.cs.kent.ac.uk/research/groups/tcs/fp/ Kent]<br />
*[http://people.cs.kuleuven.be/~tom.schrijvers/research.html Leuven]<br />
*[http://www.cs.mu.oz.au/fpu/ Melbourne]<br />
*[http://www.cse.unsw.edu.au/~pls/ New South Wales (Sydney)]<br />
*[http://www.cs.nott.ac.uk/Research/fop/ Nottingham]<br />
*[http://www.ogi.edu/csee/ OGI]<br />
*[http://metacomp.comlab.ox.ac.uk/projects Oxford]<br />
*[http://www.workingmouse.com/research/ Queensland (Brisbane)]<br />
*[http://www.cs.uu.nl/wiki/Center Utrecht]<br />
*[http://haskell.cs.yale.edu/yale/ Yale]<br />
*[http://www.cs.york.ac.uk/fp/ York]<br />
<br />
==Research positions==<br />
<br />
Advertise your research position on [[Jobs|the jobs page]].<br />
<br />
==Researchers==<br />
<br />
*[[Research_papers/Authors|Haskell people]]<br />
<br />
==Research papers==<br />
<br />
* A collection of [[Research papers|Haskell research]] papers.<br />
<br />
==Conferences==<br />
<br />
* A list of [[Conferences|conferences]] relevant to Haskell.<br />
<br />
===Haskell Symposium===<br />
<br />
*[http://haskell.org/haskell-symposium/2008/ The 2008 Haskell Symposium], Victoria, British Columbia, Canada.<br />
<br />
===Haskell Workshops===<br />
<br />
*[http://haskell.org/haskell-workshop/1995/ The First Haskell Workshop], 1995, La Jolla.<br />
*[http://www.haskell.org/haskell-workshop/1997/index.html The Second Haskell Workshop], 7 June 1997, Amsterdam, The Netherlands.<br />
*[http://www.haskell.org/HaskellWorkshop.html The Third Haskell Workshop], 1 October 1999, Paris, France.<br />
*[http://www.cs.nott.ac.uk/~gmh/hw00.html The Fourth Haskell Workshop], 17 September 2000, Montreal, Canada.<br />
*[http://haskell.org/haskell-workshop/2001/ The Fifth Haskell Workshop], September 2001, Firenze, Italy. <br />
*[http://www.cse.unsw.edu.au/~chak/hw2002/ The Sixth Haskell Workshop], October 2002, Pittsburgh, USA. <br />
*[http://www.haskell.org/haskell-workshop/2003/index.html The Seventh Haskell Workshop], August 2003, Uppsala, Sweden. <br />
*[http://www.cs.nott.ac.uk/~nhn/HW2004/ The Eigth Haskell Workshop], September 2004, Snowbird, Utah, USA.<br />
*[http://www.haskell.org/haskell-workshop/2005/ The Ninth Haskell Workshop], September 2005, Tallinn, Estonia.<br />
*[http://haskell.org/haskell-workshop/2006/ The Tenth Haskell Workshop], September 2006, Portland, Oregon, USA.<br />
*[http://haskell.org/haskell-workshop/2007/ The Eleventh Haskell Workshop], September 2007, Freiburg, Germany.<br />
<br />
[[Category:Community]]</div>Tschrijvershttps://wiki.haskell.org/index.php?title=Jobs&diff=59023Jobs2014-10-22T14:14:29Z<p>Tschrijvers: /* Academic positions */</p>
<hr />
<div>This page collects advertisements for commercial and academic positions involving Haskell or related technologies. <br />
<br />
If you are seeking Haskell jobs, or wish to recruit, good places to follow are the Haskell and Haskell-cafe mailing lists, the [http://cufp.org/jobs CUFP Job Opportunities list] and the Types mailing list (particularly for research jobs). Contacting those organisations listed on the [[Haskell in industry]] is a good idea. Joining the nascent networking site [http://www.haskellers.com Haskellers] may also prove beneficial.<br />
<br />
Please also supply the date when you add a new job opening to the list below.<br />
<br />
<br />
==Industry positions==<br />
<br />
*[http://www.bluespec.com/careers.html Bluespec, Inc.]<br />
*[http://www.checkpad.de/jobs factis research GmbH / Checkpad MED (German)]<br />
*[http://www.functor.se/careers/openings/ Functor AB]<br />
*[http://corp.galois.com/careers/ Galois, Inc]<br />
*[http://www.starling-software.com/en/employment/ Starling Software K.K.]<br />
*[http://www.tsurucapital.com/en/ Tsuru Capital LLC] <br />
<br />
===Related positions===<br />
<br />
* [https://www.erlang-solutions.com/about/careers Erlang Solutions]<br />
<br />
==Academic positions==<br />
<br />
* [http://people.cs.kuleuven.be/~tom.schrijvers/postdocposition2.html Postdoctoral position in Functional and Constraint Programming at KU Leuven] (added October, 2014)<br />
* [http://www3.imperial.ac.uk/computing/vacancies#JD0414 Research Assistant / Research Associate in Applied Computing] (added April 2014)<br />
* [http://cufp.org/jobs/programming-languages-researcher-haskell-expertise Programming Languages Researcher with Haskell Expertise] (added Sep 2010)<br />
<br />
==PhD/MSc Studentships==<br />
<br />
* [http://www.functor.se Industrial PhDs and MSc projects at Functor AB]<br />
<br />
==Internships==<br />
<br />
* [http://hackage.haskell.org/trac/ghc/wiki/Internships Internships on Haskell and GHC, at Microsoft Research, Cambridge]<br />
* [http://www.haskellers.com/jobs/5 Spring Internship at Intel to develop EDSL for parallel vector computation] (added Nov 2010)<br />
<br />
<br />
==Job sites==<br />
<br />
* [http://www.haskellers.com/jobs Haskellers]<br />
* [http://cufp.org/jobs/language/31 Commercial Users of Functional Programming]<br />
* [http://functionaljobs.com/ Functional Jobs]<br />
<br />
[[Category:Community]]</div>Tschrijvershttps://wiki.haskell.org/index.php?title=Jobs&diff=59022Jobs2014-10-22T14:12:11Z<p>Tschrijvers: /* PhD/MSc Studentships */</p>
<hr />
<div>This page collects advertisements for commercial and academic positions involving Haskell or related technologies. <br />
<br />
If you are seeking Haskell jobs, or wish to recruit, good places to follow are the Haskell and Haskell-cafe mailing lists, the [http://cufp.org/jobs CUFP Job Opportunities list] and the Types mailing list (particularly for research jobs). Contacting those organisations listed on the [[Haskell in industry]] is a good idea. Joining the nascent networking site [http://www.haskellers.com Haskellers] may also prove beneficial.<br />
<br />
Please also supply the date when you add a new job opening to the list below.<br />
<br />
<br />
==Industry positions==<br />
<br />
*[http://www.bluespec.com/careers.html Bluespec, Inc.]<br />
*[http://www.checkpad.de/jobs factis research GmbH / Checkpad MED (German)]<br />
*[http://www.functor.se/careers/openings/ Functor AB]<br />
*[http://corp.galois.com/careers/ Galois, Inc]<br />
*[http://www.starling-software.com/en/employment/ Starling Software K.K.]<br />
*[http://www.tsurucapital.com/en/ Tsuru Capital LLC] <br />
<br />
===Related positions===<br />
<br />
* [https://www.erlang-solutions.com/about/careers Erlang Solutions]<br />
<br />
==Academic positions==<br />
<br />
* [http://tomschrijvers.blogspot.be/2014/09/postdoctoral-position-in-programming.html Postdoctoral position at KU Leuven] (deadline: October 15, 2014)<br />
* [http://www3.imperial.ac.uk/computing/vacancies#JD0414 Research Assistant / Research Associate in Applied Computing] (added April 2014)<br />
* [http://cufp.org/jobs/programming-languages-researcher-haskell-expertise Programming Languages Researcher with Haskell Expertise] (added Sep 2010)<br />
<br />
==PhD/MSc Studentships==<br />
<br />
* [http://www.functor.se Industrial PhDs and MSc projects at Functor AB]<br />
<br />
==Internships==<br />
<br />
* [http://hackage.haskell.org/trac/ghc/wiki/Internships Internships on Haskell and GHC, at Microsoft Research, Cambridge]<br />
* [http://www.haskellers.com/jobs/5 Spring Internship at Intel to develop EDSL for parallel vector computation] (added Nov 2010)<br />
<br />
<br />
==Job sites==<br />
<br />
* [http://www.haskellers.com/jobs Haskellers]<br />
* [http://cufp.org/jobs/language/31 Commercial Users of Functional Programming]<br />
* [http://functionaljobs.com/ Functional Jobs]<br />
<br />
[[Category:Community]]</div>Tschrijvershttps://wiki.haskell.org/index.php?title=Jobs&diff=58855Jobs2014-09-22T15:37:02Z<p>Tschrijvers: /* Academic positions */</p>
<hr />
<div>This page collects advertisements for commercial and academic positions involving Haskell or related technologies. <br />
<br />
If you are seeking Haskell jobs, or wish to recruit, good places to follow are the Haskell and Haskell-cafe mailing lists, the [http://cufp.org/jobs CUFP Job Opportunities list] and the Types mailing list (particularly for research jobs). Contacting those organisations listed on the [[Haskell in industry]] is a good idea. Joining the nascent networking site [http://www.haskellers.com Haskellers] may also prove beneficial.<br />
<br />
Please also supply the date when you add a new job opening to the list below.<br />
<br />
<br />
==Industry positions==<br />
<br />
*[http://www.bluespec.com/careers.html Bluespec, Inc.]<br />
*[http://www.checkpad.de/jobs factis research GmbH / Checkpad MED (German)]<br />
*[http://www.functor.se/careers/openings/ Functor AB]<br />
*[http://corp.galois.com/careers/ Galois, Inc]<br />
*[http://www.starling-software.com/en/employment/ Starling Software K.K.]<br />
*[http://www.tsurucapital.com/en/ Tsuru Capital LLC] <br />
<br />
===Related positions===<br />
<br />
* [https://www.erlang-solutions.com/about/careers Erlang Solutions]<br />
<br />
==Academic positions==<br />
<br />
* [http://tomschrijvers.blogspot.be/2014/09/postdoctoral-position-in-programming.html Postdoctoral position at KU Leuven] (deadline: October 15, 2014)<br />
* [http://www3.imperial.ac.uk/computing/vacancies#JD0414 Research Assistant / Research Associate in Applied Computing] (added April 2014)<br />
* [http://cufp.org/jobs/programming-languages-researcher-haskell-expertise Programming Languages Researcher with Haskell Expertise] (added Sep 2010)<br />
<br />
==PhD/MSc Studentships==<br />
<br />
* [http://users.ugent.be/~tschrijv/phdposition3.html PhD studentship at Ghent University (posted on November 22, 2013)]<br />
* [http://www.functor.se Industrial PhDs and MSc projects at Functor AB]<br />
<br />
==Internships==<br />
<br />
* [http://hackage.haskell.org/trac/ghc/wiki/Internships Internships on Haskell and GHC, at Microsoft Research, Cambridge]<br />
* [http://www.haskellers.com/jobs/5 Spring Internship at Intel to develop EDSL for parallel vector computation] (added Nov 2010)<br />
<br />
<br />
==Job sites==<br />
<br />
* [http://www.haskellers.com/jobs Haskellers]<br />
* [http://cufp.org/jobs/language/31 Commercial Users of Functional Programming]<br />
* [http://functionaljobs.com/ Functional Jobs]<br />
<br />
[[Category:Community]]</div>Tschrijvershttps://wiki.haskell.org/index.php?title=Jobs&diff=57131Jobs2013-11-22T12:36:38Z<p>Tschrijvers: /* PhD/MSc Studentships */</p>
<hr />
<div>This page collects advertisements for commercial and academic positions involving Haskell or related technologies. <br />
<br />
If you are seeking Haskell jobs, or wish to recruit, good places to follow are the Haskell and Haskell-cafe mailing lists, the [http://cufp.org/jobs CUFP Job Opportunities list] and the Types mailing list (particularly for research jobs). Contacting those organisations listed on the [[Haskell in industry]] is a good idea. Joining the nascent networking site [http://www.haskellers.com Haskellers] may also prove beneficial.<br />
<br />
Please also supply the date when you add a new job opening to the list below.<br />
<br />
<br />
==Industry positions==<br />
<br />
*[http://www.bluespec.com/about/careers.htm Bluespec, Inc.]<br />
*[http://www.functor.se/careers/openings/ Functor AB]<br />
*[http://corp.galois.com/careers/ Galois, Inc]<br />
*[http://www.starling-software.com/en/employment/ Starling Software K.K.]<br />
*[http://www.tsurucapital.com/en/ Tsuru Capital LLC] <br />
<br />
===Related positions===<br />
<br />
* [https://www.erlang-solutions.com/about/careers Erlang Solutions]<br />
<br />
==Academic positions==<br />
<br />
* [http://cufp.org/jobs/programming-languages-researcher-haskell-expertise Programming Languages Researcher with Haskell Expertise] (added Sep 2010)<br />
<br />
<br />
==PhD/MSc Studentships==<br />
<br />
* [http://users.ugent.be/~tschrijv/phdposition3.html PhD studentship at Ghent University (posted on November 22, 2013)]<br />
* [http://www.functor.se Industrial PhDs and MSc projects at Functor AB]<br />
<br />
==Internships==<br />
<br />
* [http://hackage.haskell.org/trac/ghc/wiki/Internships Internships on Haskell and GHC, at Microsoft Research, Cambridge]<br />
* [http://www.haskellers.com/jobs/5 Spring Internship at Intel to develop EDSL for parallel vector computation] (added Nov 2010)<br />
<br />
<br />
==Job sites==<br />
<br />
* [http://www.haskellers.com/jobs Haskellers]<br />
* [http://cufp.org/jobs/language/31 Commercial Users of Functional Programming]<br />
* [http://functionaljobs.com/ Functional Jobs]<br />
<br />
[[Category:Community]]</div>Tschrijvershttps://wiki.haskell.org/index.php?title=Jobs&diff=43630Jobs2011-12-16T16:02:47Z<p>Tschrijvers: /* PhD/MSc Studentships */</p>
<hr />
<div>This page collects advertisements for commercial and academic positions involving Haskell or related technologies. <br />
<br />
If you are seeking Haskell jobs, or wish to recruit, good places to follow are the Haskell and Haskell-cafe mailing lists, the [http://cufp.org/jobs CUFP Job Opportunities list] and the Types mailing list (particularly for research jobs). Contacting those organisations listed on the [[Haskell in industry]] is a good idea. Joining the nascent networking site [http://haskellers.com Haskellers] may also prove beneficial.<br />
<br />
Please also supply the date when you add a new job opening to the list below.<br />
<br />
==Industry positions==<br />
<br />
*[http://www.aetion.com/ Aetion Technologies LLC]<br />
*[http://www.bluespec.com/about/careers.htm Bluespec, Inc.]<br />
*[http://www.galois.com/company/careers Galois, Inc]<br />
*[http://www.starling-software.com/en/employment/ Starling Software K.K.]<br />
*[http://www.tsurucapital.com/en/ Tsuru Capital LLC] <br />
<br />
===Related positions===<br />
* [http://www.erlang-solutions.com/jobs/ Erlang Solutions]<br />
* [http://www.simcorp.com/Home/Careers/Jobs/Denmark.aspx SimCorp is looking for Ocaml Software Developers]<br />
<br />
==Academic positions==<br />
* [http://cufp.org/jobs/programming-languages-researcher-haskell-expertise] Programming Languages Researcher with Haskell Expertise (added Sep 2010)<br />
<br />
==PhD/MSc Studentships==<br />
<br />
* [http://users.ugent.be/~tschrijv/phdposition2.html PhD studentship at Ghent University] <br />
* PhD studentships in Nottingham (deadline 1st March 2011) [http://www.cs.nott.ac.uk/~gmh/phd-advert.txt]<br />
<br />
==Internships==<br />
<br />
* [http://hackage.haskell.org/trac/ghc/wiki/Internships Internships on Haskell and GHC, at Microsoft Research, Cambridge]<br />
* [http://www.haskellers.com/jobs/5/ Spring Internship at Intel to develop EDSL for parallel vector computation] (added Nov 2010)<br />
<br />
<br />
==Job sites==<br />
<br />
* [http://www.haskellers.com/jobs/ Haskellers]<br />
* [http://cufp.org/jobs/language/31 Commercial Users of Functional Programming]<br />
* [http://functionaljobs.com/ Functional Jobs]<br />
<br />
[[Category:Community]]</div>Tschrijvershttps://wiki.haskell.org/index.php?title=Conferences&diff=41683Conferences2011-08-19T08:18:46Z<p>Tschrijvers: /* International Symposium on Functional and Logic Programming (FLOPS) */</p>
<hr />
<div>Haskell programmers publish a great deal of [[Research papers|research]]<br />
at conferences, which are also great places to meet and discuss <br />
Haskell and its future. The following is a list of some of the<br />
conferences at which Haskellers and their research appears.<br />
<br />
For a calendar-like interface, see [http://www.unsafeperformio.com/confs.php Andy Gill's page].<br />
<br />
== The Haskell Symposium ==<br />
<br />
* [http://haskell.org/haskell-symposium/ The Haskell Symposium].<br />
<br />
The Haskell Symposium is an annual symposium organized in affiliation with<br />
the International Conference on Functional Programming (ICFP). The<br />
workshop is sponsored by the Association for Computing Machinery (ACM)<br />
under the aegis of the ACM Special Interest Group on Programming<br />
Languages (SIGPLAN).<br />
<br />
The purpose of the Haskell Symposium is to discuss experience with<br />
Haskell, and future developments for the language. The scope of the<br />
symposium includes all aspects of the design, semantics, theory,<br />
application, implementation, and teaching of Haskell.<br />
<br />
== The International Conference on Functional Programming (ICFP) ==<br />
<br />
* [http://www.cs.luc.edu/icfp/ The International Conference on Functional Programming (ICFP)]<br />
<br />
ICFP (International Conference on Functional Programming) is an annual<br />
programming language conference. It is sponsored by the Association for<br />
Computing Machinery under the aegis of the ACM Special Interest Group on<br />
Programming Languages (SIGPLAN), in association with Working Group 2.8<br />
of the International Federation of Information Processing (IFIP).<br />
<br />
== Commercial Users of Functional Programming (CUFP) ==<br />
<br />
* [http://www.galois.com/cufp/ Commercial Users of Functional Programming Workshop]<br />
<br />
The goal of CUFP is to build a community for users of functional<br />
programming languages and technology, be they using functional languages<br />
in their professional lives, in an open source project (other than<br />
implementation of functional languages), as a hobby, or any combination<br />
thereof. In short: anyone who uses functional programming as a means,<br />
but not an end<br />
<br />
== International Symposium on Functional and Logic Programming (FLOPS) ==<br />
<br />
* [http://www.org.kobe-u.ac.jp/flops2012/ FLOPS 2012]<br />
<br />
FLOPS is a forum for research on all issues concerning declarative programming, including functional programming and logic programming, and aims to promote cross-fertilization and integration between the two paradigms.<br />
<br />
== Principles of Programming Languages (POPL) ==<br />
<br />
* [http://www.cs.ucsd.edu/popl/07/ Principles of Programming Languages (POPL)]<br />
<br />
== Programming Language Design and Implementation (PLDI) ==<br />
<br />
* [http://research.microsoft.com/conferences/pldi06/ Programming Language Design and Implementation (PLDI)]<br />
<br />
== Implementation of Functional Languages (IFL) ==<br />
<br />
* [http://plc.inf.elte.hu/ifl2006/ Implementation of Functional Languages (IFL)]<br />
<br />
== Practical Aspects of Declarative Languages (PADL) ==<br />
<br />
* [http://www.informatik.uni-kiel.de/~mh/padl07 Practical Applications of Declarative Languages (PADL)]<br />
<br />
== Principles and Practice of Declarative Programming (PPDP) ==<br />
<br />
* [http://www.risc.jku.at/about/conferences/ppdp2010/ Principles and Practice of Declarative Programming (PPDP)]<br />
<br />
== Asian Symposium on Programming Languages and Systems (APLAS) ==<br />
<br />
* [http://www.kb.ecei.tohoku.ac.jp/aplas2006/ Asian Symposium on Programming Languages and Systems (APLAS]<br />
<br />
== Declarative Aspects of Multicore Programming (DAMP) ==<br />
<br />
* [http://www.cs.cmu.edu/~damp Declarative Aspects of Multicore Programming (DAMP)]<br />
<br />
== Types in Language Design and Implementation (TLDI) ==<br />
<br />
* [http://www.cs.berkeley.edu/%7Enecula/tldi07/ Types in Language Design and Implementation (TLDI)]<br />
<br />
== Trends in Functional Programming (TFP) ==<br />
<br />
* [http://www.tifp.org/ Trends in Functional Programming]<br />
<br />
== Principles, Logics, and Implementations of High-Level Programming Languages (PLI) ==<br />
<br />
* [http://pli2002.cs.brown.edu/ PLI]<br />
<br />
== Types in Compilation Workshop (TIC) ==<br />
<br />
* [http://www.cs.cmu.edu/~crary/tic00/ Types in Compilation (TIC)]<br />
<br />
== Practical Aspects of High-level Parallel Programming (PAPP) ==<br />
<br />
* [http://f.loulergue.free.fr/PAPP2007/index.html Practical Aspects of High-level Parallel Programming]<br />
<br />
== Federated Conference on Rewriting, Deduction, and Programming (RDP) ==<br />
<br />
* [http://www.lsv.ens-cachan.fr/rdp07/ Federated Conference on Rewriting, Deduction, and Programming]<br />
<br />
== Typed Lambda Calculi and Applications (TLCA) ==<br />
<br />
* [http://www.lsv.ens-cachan.fr/rdp07/tlca.html Typed Lambda Calculi and Applications (TLCA '07)]<br />
<br />
== International Workshop on Functional and Declarative Programming in Education ==<br />
<br />
* [http://www.informatik.uni-kiel.de/~mh/publications/reports/fdpe02/ FDPE]<br />
<br />
== Advanced Functional Programming Spring School (AFP) ==<br />
<br />
* [http://www.cs.ut.ee/afp04/ Advanced Functional Programming: 5th International School]<br />
<br />
== Integrated Formal Methods (IFM) ==<br />
<br />
* [http://www.softeng.ox.ac.uk/ifm2007/ Integrated Formal Methods 2007]<br />
<br />
== UTP'07 at IFM: Unifying Theories of Programming ==<br />
<br />
* [http://www.ifm2007.org Unifying Theories of Programming]<br />
<br />
== Systems Software Verification (SSV) ==<br />
<br />
* [http://nicta.com.au/ssv08/ Systems Software Verification Workshop]<br />
<br />
Please add more Haskell-related conferences as they appear.<br />
<br />
<br />
<br />
[[Category:Events]]</div>Tschrijvershttps://wiki.haskell.org/index.php?title=Conferences&diff=41682Conferences2011-08-19T08:18:21Z<p>Tschrijvers: added FLOPS</p>
<hr />
<div>Haskell programmers publish a great deal of [[Research papers|research]]<br />
at conferences, which are also great places to meet and discuss <br />
Haskell and its future. The following is a list of some of the<br />
conferences at which Haskellers and their research appears.<br />
<br />
For a calendar-like interface, see [http://www.unsafeperformio.com/confs.php Andy Gill's page].<br />
<br />
== The Haskell Symposium ==<br />
<br />
* [http://haskell.org/haskell-symposium/ The Haskell Symposium].<br />
<br />
The Haskell Symposium is an annual symposium organized in affiliation with<br />
the International Conference on Functional Programming (ICFP). The<br />
workshop is sponsored by the Association for Computing Machinery (ACM)<br />
under the aegis of the ACM Special Interest Group on Programming<br />
Languages (SIGPLAN).<br />
<br />
The purpose of the Haskell Symposium is to discuss experience with<br />
Haskell, and future developments for the language. The scope of the<br />
symposium includes all aspects of the design, semantics, theory,<br />
application, implementation, and teaching of Haskell.<br />
<br />
== The International Conference on Functional Programming (ICFP) ==<br />
<br />
* [http://www.cs.luc.edu/icfp/ The International Conference on Functional Programming (ICFP)]<br />
<br />
ICFP (International Conference on Functional Programming) is an annual<br />
programming language conference. It is sponsored by the Association for<br />
Computing Machinery under the aegis of the ACM Special Interest Group on<br />
Programming Languages (SIGPLAN), in association with Working Group 2.8<br />
of the International Federation of Information Processing (IFIP).<br />
<br />
== Commercial Users of Functional Programming (CUFP) ==<br />
<br />
* [http://www.galois.com/cufp/ Commercial Users of Functional Programming Workshop]<br />
<br />
The goal of CUFP is to build a community for users of functional<br />
programming languages and technology, be they using functional languages<br />
in their professional lives, in an open source project (other than<br />
implementation of functional languages), as a hobby, or any combination<br />
thereof. In short: anyone who uses functional programming as a means,<br />
but not an end<br />
<br />
== International Symposium on Functional and Logic Programming (FLOPS) ==<br />
<br />
* [http://www.org.kobe-u.ac.jp/flops2012/]<br />
<br />
FLOPS is a forum for research on all issues concerning declarative programming, including functional programming and logic programming, and aims to promote cross-fertilization and integration between the two paradigms.<br />
<br />
== Principles of Programming Languages (POPL) ==<br />
<br />
* [http://www.cs.ucsd.edu/popl/07/ Principles of Programming Languages (POPL)]<br />
<br />
== Programming Language Design and Implementation (PLDI) ==<br />
<br />
* [http://research.microsoft.com/conferences/pldi06/ Programming Language Design and Implementation (PLDI)]<br />
<br />
== Implementation of Functional Languages (IFL) ==<br />
<br />
* [http://plc.inf.elte.hu/ifl2006/ Implementation of Functional Languages (IFL)]<br />
<br />
== Practical Aspects of Declarative Languages (PADL) ==<br />
<br />
* [http://www.informatik.uni-kiel.de/~mh/padl07 Practical Applications of Declarative Languages (PADL)]<br />
<br />
== Principles and Practice of Declarative Programming (PPDP) ==<br />
<br />
* [http://www.risc.jku.at/about/conferences/ppdp2010/ Principles and Practice of Declarative Programming (PPDP)]<br />
<br />
== Asian Symposium on Programming Languages and Systems (APLAS) ==<br />
<br />
* [http://www.kb.ecei.tohoku.ac.jp/aplas2006/ Asian Symposium on Programming Languages and Systems (APLAS]<br />
<br />
== Declarative Aspects of Multicore Programming (DAMP) ==<br />
<br />
* [http://www.cs.cmu.edu/~damp Declarative Aspects of Multicore Programming (DAMP)]<br />
<br />
== Types in Language Design and Implementation (TLDI) ==<br />
<br />
* [http://www.cs.berkeley.edu/%7Enecula/tldi07/ Types in Language Design and Implementation (TLDI)]<br />
<br />
== Trends in Functional Programming (TFP) ==<br />
<br />
* [http://www.tifp.org/ Trends in Functional Programming]<br />
<br />
== Principles, Logics, and Implementations of High-Level Programming Languages (PLI) ==<br />
<br />
* [http://pli2002.cs.brown.edu/ PLI]<br />
<br />
== Types in Compilation Workshop (TIC) ==<br />
<br />
* [http://www.cs.cmu.edu/~crary/tic00/ Types in Compilation (TIC)]<br />
<br />
== Practical Aspects of High-level Parallel Programming (PAPP) ==<br />
<br />
* [http://f.loulergue.free.fr/PAPP2007/index.html Practical Aspects of High-level Parallel Programming]<br />
<br />
== Federated Conference on Rewriting, Deduction, and Programming (RDP) ==<br />
<br />
* [http://www.lsv.ens-cachan.fr/rdp07/ Federated Conference on Rewriting, Deduction, and Programming]<br />
<br />
== Typed Lambda Calculi and Applications (TLCA) ==<br />
<br />
* [http://www.lsv.ens-cachan.fr/rdp07/tlca.html Typed Lambda Calculi and Applications (TLCA '07)]<br />
<br />
== International Workshop on Functional and Declarative Programming in Education ==<br />
<br />
* [http://www.informatik.uni-kiel.de/~mh/publications/reports/fdpe02/ FDPE]<br />
<br />
== Advanced Functional Programming Spring School (AFP) ==<br />
<br />
* [http://www.cs.ut.ee/afp04/ Advanced Functional Programming: 5th International School]<br />
<br />
== Integrated Formal Methods (IFM) ==<br />
<br />
* [http://www.softeng.ox.ac.uk/ifm2007/ Integrated Formal Methods 2007]<br />
<br />
== UTP'07 at IFM: Unifying Theories of Programming ==<br />
<br />
* [http://www.ifm2007.org Unifying Theories of Programming]<br />
<br />
== Systems Software Verification (SSV) ==<br />
<br />
* [http://nicta.com.au/ssv08/ Systems Software Verification Workshop]<br />
<br />
Please add more Haskell-related conferences as they appear.<br />
<br />
<br />
<br />
[[Category:Events]]</div>Tschrijvershttps://wiki.haskell.org/index.php?title=Research_papers/Domain_specific_languages&diff=30297Research papers/Domain specific languages2009-09-27T18:00:54Z<p>Tschrijvers: added Monadic Constraint Programming paper</p>
<hr />
<div>__TOC__<br />
<br />
==Domain specific languages==<br />
<br />
;[http://legacy.cs.uu.nl/daan/download/papers/dsec.ps Domain Specific Embedded Compilers]<br />
:Daan Leijen and Erik Meijer. 2nd USENIX Conference on Domain-Specific Languages (DSL'99), Austin, Texas, October 1999. Also appeared in ACM SIGPLAN Notices 35, 1, January 2000.<br />
<br />
;[http://conal.net/papers/jfp-saig/ Compiling Embedded Languages]<br />
:Conal Elliott, Sigbjorn Finne, Oege de Moor. Journal of Functional Programming, 13(2), 2003.<br />
<br />
;[http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.53.5061 Modular Domain Specific Languages and Tools]<br />
:Hudak (1998) (cited by 92)<br />
<br />
;[https://eprints.kfupm.edu.sa/28924/ Building Domain-Specific Embedded Languages] ([http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.49.6020 citeseer link])<br />
:Paul Hudak (cited by 102)<br />
<br />
;[http://www.usenix.org/publications/library/proceedings/dsl99/full_papers/leijen/leijen.ps Domain Specific Embedded Compilers] <br />
:D Leijen, E Meijer (cited by 88)<br />
<br />
;[http://portal.acm.org/citation.cfm%3Fid%3D317765.317794 Haskell and XML: generic combinators or type-based translation?]<br />
:M Wallace, C Runciman - ACM SIGPLAN Notices, 1999 <br />
<br />
;[http://www.springerlink.com/index/RPRWGR7LHTXBT2DW.pdf Modeling HTML in Haskell]<br />
:P Thiemann - Practical Applications of Declarative Languages, 2000 (cited by 24)<br />
<br />
;[http://portal.acm.org/citation.cfm%3Fcoll%3DGUIDE%26dl%3DGUIDE%26id%3D331975 DSL implementation using staging and monads]<br />
:T Sheard, E Pasalic - Proceedings of the 2nd conference on Domain-specific languages, 1999<br />
<br />
;[http://www.informatik.uni-freiburg.de/~thiemann/papers/wflp02.ps.gz Programmable type systems for domain specific languages]<br />
:P Thiemann Electronic Notes in Theoretical Computer Science, 2002<br />
<br />
;[http://portal.acm.org/citation.cfm%3Fid%3D1052935 An embedded domain-specific language for type-safe server-side web scripting]<br />
:P Thiemann, ACM Transactions on Internet Technology (TOIT), 2005<br />
<br />
;[http://www.informatik.uni-freiburg.de/~thiemann/papers/modeling.ps.gz A typed representation for HTML and XML documents in Haskell]<br />
:P Thiemann, Journal of Functional Programming, 2003 (cited by 38)<br />
<br />
;[http://portal.acm.org/citation.cfm%3Fid%3D331963.331976 Monadic robotics]<br />
:J Peterson, G Hager.<br />
<br />
;[ftp://cse.ogi.edu/pub/pacsoft/papers/dsl-tools.ps Defining and Implementing Closed, Domain-Specific Languages]<br />
:RB Kieburtz - Invited talk, 2000 <br />
<br />
===Rapid prototyping===<br />
<br />
;[http://www.haskell.org/frob/icse99/visionpaper.ps Prototyping Real-Time Vision Systems: An Experiment in DSL Design]<br />
:A. Reid, J. Peterson, G. Hager and P. Hudak, In Proceedings of International Conference on Software Engineering (ICSE'99), Los Angeles, CA. 16-22 May, 1999.<br />
<br />
;[http://www.haskell.org/yale/papers/padl01-vision/index.html FVision: A Declarative Language for Visual Tracking]<br />
:J. Peterson, P. Hudak, A. Reid and G. Hager. In Proceedings of Third International Symposium on Practical Applications of Declarative Languages PADL'01, March 2001.<br />
<br />
===Graphics===<br />
<br />
;[https://www.usenix.org/publications/library/proceedings/dsl97/full_papers/elliott/elliott.pdf Modeling Interactive 3D and Multimedia Animation with an Embedded Language]<br />
:Conal Elliott (cited by 35)<br />
<br />
;[http://conal.net/papers/Vertigo/ Programming Graphics Processors Functionally]<br />
:Conal Elliott. Proceedings of the 2004 Haskell Workshop.<br />
<br />
;[http://conal.net/papers/functional-images/ Functional Images]<br />
:Conal Elliott. In The Fun of Programming, March 2003.<br />
<br />
;[http://conal.net/papers/Eros/ Tangible Functional Programming]<br />
:Conal Elliott, ICFP 07<br />
<br />
===Hardware design===<br />
<br />
;[http://www.cs.chalmers.se/~koen/pubs/charme01-sorter.pdf The Design and Verification of a Sorter Core]<br />
:Koen Claessen, Mary Sheeran, and Satnam Singh. In Proc. of Conference on Correct Hardware Design and Verification Methods (CHARME), Lecture Notes in Computer Science, Springer Verlag, 2001.<br />
<br />
;[http://www.cs.chalmers.se/~koen/Papers/lic.ps An Embedded Language Approach to Hardware Description and Verification]<br />
:Koen Claessen. Dept. of Computer Science and Engineering, Chalmers University of Technology, Lic. thesis, August 2000.<br />
<br />
;[http://www.cs.chalmers.se/~koen/pubs/phd01-thesis.ps Embedded Languages for Describing and Verifying Hardware]<br />
:Koen Claessen. Dept. of Computer Science and Engineering, Chalmers University of Technology, Ph.D. thesis, April 2001.<br />
<br />
;[http://www.cs.chalmers.se/~koen/pubs/fdpe02-lava.ps An Embedded Language Approach to Teaching Hardware Compilation]<br />
:Koen Claessen and Gordon Pace. In Proc. of Workshop on Functional and Declarative Programming in Education (FDPE), 2002.<br />
<br />
;[http://www.cs.chalmers.se/~koen/Papers/constructive.ps Safety Property Verification of Cyclic Circuits]<br />
:Koen Claessen. June 2002.<br />
<br />
;[http://www.cs.chalmers.se/~koen/Papers/paps.ps Verification of Hardware Systems with First-Order Logic]<br />
:Koen Claessen, Reiner Hähnle, Johan Mårtensson. PaPS 2002. 2002.<br />
<br />
;[http://www.cs.chalmers.se/~koen/Papers/dcc-hwcomp.ps An Embedded Language Framework for Hardware Compilation]<br />
:Koen Claessen, Gordon Pace. DCC 2002. 2002.<br />
<br />
;[http://www.cs.chalmers.se/~koen/Papers/obs-shar.ps Observable Sharing for Functional Circuit Description]<br />
:Koen Claessen and David Sands. ASIAN '99. 1999.<br />
<br />
;[http://www.cs.chalmers.se/~bjesse/fftpaper.ps.gz Automatic Verification of Combinational and Pipelined FFT Circuits]<br />
:Per Bjesse. CAV. 1999<br />
<br />
;[http://content.ohsu.edu/cdm4/item_viewer.php?CISOROOT=/etd&CISOPTR=212&CISOBOX=1&REC=9 Algebraic Specification and Verification of Processor Microarchitectures]<br />
:John Matthews. PhD. Thesis. Oregon Graduate Institute. 2000.<br />
<br />
;[http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.26.8326 Symbolic Simulation of Microprocessor Models using Type Classes in Haskell]<br />
:Nancy A. Day, Jeffrey R. Lewis and Byron Cook. CHARME'99. September 1999.<br />
<br />
;[http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.37.4284 On Embedding a Microarchitectural Design Language within Haskell]<br />
:John Launchbury, Jeff Lewis and Byron Cook. ICFP'99. 1999. <br />
<br />
;[http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.22.5519 Elementary Microarchitecture Algebra]<br />
:John Matthews and John Launchbury. CAV '99. 1999.<br />
<br />
;[http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.24.1486 Specifying Superscalar Microprocessors with Hawk]<br />
:Byron Cook, John Launchbury and John Matthews. FTH '98. 1998.<br />
<br />
;[https://wiki.ittc.ku.edu/lambda/Image:Matthews-Microprocessor_Specification_in_HAWK.pdf Microprocessor Specification in Hawk]<br />
:John Matthews, John Launchbury and Byron Cook. ICCL '98. 1998.<br />
<br />
====Lava====<br />
<br />
;[http://www.cs.chalmers.se/~koen/Papers/lava.ps Lava: Hardware Design in Haskell]<br />
:Per Bjesse, Koen Claessen, Mary Sheeran, Satnam Singh<br />
<br />
;[http://www.math.chalmers.se/~koen/pubs/entry-sttt03-lava.html Using Lava to Design and Verify Recursive and Periodic Sorters]<br />
:Koen Claessen, Mary Sheeran, and Satnam Singh. In International Journal on Software Tools for Technology Transfer, vol. 4 (3), pp. 349--358, Springer Verlag, 2003.<br />
<br />
;[http://www.math.chalmers.se/~koen/pubs/entry-fop-lava.html Functional Hardware Description in Lava]<br />
:Koen Claessen, Mary Sheeran, and Satnam Singh. In Jeremy Gibbons and Oege de Moor (eds.), The Fun of Programming, Cornerstones of Computing, pp. 151--176, Palgrave, 2003.<br />
<br />
;[http://www.cs.chalmers.se/~koen/Lava/tutorial.ps A Lava Tutorial]<br />
:Koen Claessen, Mary Sheeran. April 2000.<br />
<br />
===Network programming===<br />
<br />
;[http://www.fujipress.jp/finder/xslt.php?mode=present&inputfile=IPSTP004700160002.xml A Network Programming Framework in Haskell Based on Asynchronous Localized pi-calculus]<br />
:Keigo Imai ,Shoji Yuen ,Kiyoshi Agusa. Graduate School of Information Science, Nagoya University Journal ref: IPSJ Transactions on Programming, Vol.47, No.16 pp. 10-28, 2006<br />
<br />
===Logic and constraint programming===<br />
<br />
;[http://www.cs.chalmers.se/~koen/pubs/haskell00-typedlp.ps Typed Logical Variables in Haskell]<br />
:Koen Claessen and Peter Ljunglöf. In Proc. of Haskell Workshop, ACM SIGPLAN, 2000. 1999<br />
<br />
;[http://www.informatik.uni-bonn.de/~ralf/publications/Prolog.ps.gz Prolog's control constructs in a functional setting - Axioms and implementation]<br />
:Ralf Hinze. International Journal of Foundations of Computer Science. 12 (2). 2001.<br />
<br />
;[http://www.cs.kuleuven.be/~toms/Research/papers/modref2009.pdf Monadic Constraint Programming]<br />
:Tom Schrijvers, Peter Stuckey and Phil Wadler. Journal of Functional Programming, 2009.<br />
<br />
[[Category:Research]]</div>Tschrijvershttps://wiki.haskell.org/index.php?title=AngloHaskell/2009&diff=28468AngloHaskell/20092009-06-03T08:30:29Z<p>Tschrijvers: </p>
<hr />
<div>AngloHaskell 2009 is taking place on the 7th of August at MSR Cambridge, with further activities on the 8th. It's free, and everyone is invited! Simply add your name to the wiki and we'll see you there :-)<br />
<br />
We could use local contacts and someone to act as organisational contact on the day. People willing to put someone up for the night (even if on a floor) would also be much appreciated. Any volunteers?<br />
<br />
== Date and Venue ==<br />
<br />
7th-8th of August in Cambridge, UK, starting with talks at Microsoft Research and with more planning to happen below.<br />
<br />
=== Directions to MSR ===<br />
<br />
MSR has [http://research.microsoft.com/aboutmsr/visitmsr/cambridge/directions.aspx some directions], which can be best summarised as ‘get a taxi’. Here is (hopefully) a [http://earth.google.com/ Google Earth] [[Media:Microsoft_Research,_Cambridge.kmz|location]] of MSR, as well as a [http://maps.google.com/maps?q=CB3+0FB&ll=52.211499,0.117073&spn=0.02677,0.086517 Google Maps link]. (J J Thomson Avenue is immediately west of Clerk Maxwell Road.)<br />
<br />
If you do take a taxi and the driver doesn't know where it is, tell him or her to drive down Madingley Road until you reach the West Cambridge site, J J Thomson Avenue. The Computer Laboratory (next door) has [http://www.cl.cam.ac.uk/UoCCL/contacts/#gettinghere marginally better instructions].<br />
<br />
The fastest way to MSR (on foot and public transport) from the station is to [http://maps.google.com/maps?saddr=CB1+2JW&daddr=Trumpington+Road,+Cambridge cut through to Trumpington Road via Bateman Street] (don't follow the driving directions!), and take the Citi 4 or Uni 4. There's a bus stop just across the road from Bateman Street.<br />
<br />
To get to the city centre by bus, take the Citi 1 or Citi 3. Do ask to make sure they're going in the right direction though! There are also a number of clearly marked shuttle busses between the centre and station running during the day every 10 minutes or so.<br />
<br />
To walk to the centre (20 minutes not carrying luggage), go straight down the road facing you when you come out of the station, bear right when the road ends at some traffic lights / a WW1 memorial / the botanic gardens, and keep walking straight (Hills Road / Regent St / St Andrews St) for quite a while until you reach a pedestrianised bit, at which point you are in the centre.<br />
<br />
From the city centre to MSR, you can catch the number 77 Madingley Road Park and Ride which goes from bus stop M on Emma St. (Or find your way to Pembroke or Silver Street, and catch the Citi 4 / Uni 4 from there.) (Note that the 77 doesn't stop by MSR any more, it goes to the park and ride from which you have to walk back, 10-15 mins. This caught me out the other day --SimonM).<br />
<br />
==== Parking ====<br />
<br />
To be verified:<br />
<br />
Some parking spaces will be available around the back of the MSR building. To get out again, drivers will need to talk to reception to obtain a token.<br />
<br />
== Attendees ==<br />
<br />
Per last year, all attendees should '''bring or make a nametag''' that identifies you by your real name and/or IRC name. If anyone wants to drag a roll of stickers and a pen along that'll help!<br />
<br />
If you can't make the start on Friday, or can only make it on Saturday, that's fine. If you're not sure where everyone's going to be, give one of the contacts a call or a text.<br />
<br />
=== Definite ===<br />
<br />
* Philippa Cowderoy<br />
* Neil Mitchell<br />
* Eric Kow<br />
* Tom Schrijvers<br />
<br />
=== Possible ===<br />
<br />
== Lodging ==<br />
<br />
It's likely that there'll be people in need of crashspace and so forth, so please organise here! Both offers and requests are good.<br />
<br />
=== Nearby Colleges ===<br />
<br />
Many of undergraduate colleges (which are really glorified halls of residence) offer cheap accommodation over the holidays. Locations near MSR include Churchill College, Wolfson Court (an annexe of Girton College), Fitzwillian College, Robinson College, New Hall (female only) and Burwells Field (an annexe of Trinity College).<br />
<br />
[http://www.cam.ac.uk/map/v4/drawmap.cgi?mp=main;xx=900;yy=560;mt=c;mx=759;my=467;ms=75;tl=Microsoft%20Research This map] might prove useful.<br />
<br />
-- [http://www.dysfunctor.org/ Peter McArthur]<br />
<br />
=== Hostels ===<br />
<br />
There's a fairly inexpensive [http://www.yha.org.uk/find-accommodation/east-of-england/hostels/cambridge/index.aspx YHA hostel] in Cambridge. There may be others.<br />
<br />
Another guest house right next to the station is Tenison Towers (01223 363924).<br />
<br />
== Programme ==<br />
<br />
Planning will be taking place on IRC as per previous years: #anglohaskell on irc.freenode.net<br />
<br />
If you're having trouble following things on IRC, the discussion page on the wiki might be a good place to leave comments and questions.<br />
<br />
Previous years in Cambridge we had talks in the day on a Friday, followed by pubbage in the evening and assorted activities on the Saturday. This seemed to work, so we'll follow a similar model this year. Sadly we can't have talk space at MSR on a Saturday.<br />
<br />
=== Talks ===<br />
<br />
Volunteers please! Previously we have had a largely more practical set of talks than you might find at Fun in the Afternoon or an academic event. This was a good thing, and some of the best talks were from people who were far from considering themselves as experts, so feel free to tell us about your experiences.<br />
<br />
In the event that more talks are offered than we have time for at MSR, we'll have to work out what we can do to find more time.<br />
<br />
Talks planned and/or offered:<br />
<br />
* Neil Mitchell - hopefully "Make Considered Harmful"<br />
* Tom Schrijvers - "Monadic Constraint Programming"<br />
<br />
==== Abstracts ====<br />
<br />
People giving talks should add these as they have them :-)<br />
<br />
* Monadic Constraint Programming<br />
<br />
A constraint programming system combines two essential components: a constraint solver and a search engine. The constraint solver reasons about satisfiability of conjunctions of constraints, and the search engine controls the search for solutions by iteratively exploring a disjunctive search tree defined by the constraint program.<br />
<br />
The Monadic Constraint Programming framework gives a monadic definition of constraint programming where the solver is defined as a monad threaded through the monadic search tree. Search and search strategies can then be defined as firstclass objects that can themselves be built or extended by composable search transformers. Search transformers give a powerful and unifying approach to viewing search in constraint programming, and the resulting constraint programming system is first class and extremely flexible. <br />
<br />
=== Other activity ===<br />
<br />
After Friday's talks, food and drink would be a good idea! Curry is traditional and probably the default, but we're open to other suggestions. After that, we'll retreat to a pub for the evening.<br />
<br />
Repeating previous years, I suggest we go to [http://www.beerintheevening.com/pubs/s/13/1361/Regal/Cambridge The Regal] for brunch on Saturday to kick off with. That's the Wetherspoons from last year. After that, punting again if it's not raining too much? Any suggestions for if it's wet?<br />
<br />
[[User:PhilippaCowderoy|PhilippaCowderoy]]<br />
<br />
[[Category:Events]]</div>Tschrijvershttps://wiki.haskell.org/index.php?title=Research_papers/Type_systems&diff=28213Research papers/Type systems2009-05-15T11:18:34Z<p>Tschrijvers: </p>
<hr />
<div>__TOC__<br />
<br />
==Haskell semantics==<br />
<br />
;[http://research.microsoft.com/~simonpj/Papers/static-semantics.dvi.gz A static semantics for Haskell]<br />
:SL Peyton Jones and PL Wadler, (draft), Department of Computing Science, University of Glasgow, 1992. (Cited by 20)<br />
<br />
;[http://haskell.org/onlinereport/dynamic-semantics.dvi.gz A Dynamic Semantics for Haskell] <br />
:Kevin Hammond and Cordelia Hall, (draft), University of Glasgow, 1992, 23 pages.<br />
<br />
;[http://citeseer.ist.psu.edu/424440.html Typing Haskell in Haskell] <br />
:Mark P. Jones, In Proceedings of the 1999 Haskell Workshop, Paris, France, October 1999. Published in Technical Report UU-CS-1999-28, Department of Computer Science, University of Utrecht. (Cited by 66)<br />
<br />
;[http://www.pms.informatik.uni-muenchen.de/mitarbeiter/panne/haskell_libs/hsparser.html HParser]<br />
:A parser for Haskell written purely in Haskell (using the Happy parser generator).<br />
<br />
;[http://www.cse.ogi.edu/~hallgren/Talks/LHiH/ A Lexer for Haskell in Haskell]<br />
:Thomas Hallgren, PacSoft Oregon Graduate Institute, 14 January, 2002<br />
<br />
;[http://citeseer.ist.psu.edu/launchbury93natural.html A Natural Semantics for Lazy Evaluation]<br />
:John Launchbury, Conference Record of the Twentieth Annual ACM SIGPLAN-SIGACT Symposium on Principles of Programming Languages, Charleston, South Carolina, 144--154, 1993.<br />
<br />
;[http://www.cs.nott.ac.uk/~gmh/papers/11.ps A Space Semantics for Core Haskell]<br />
:Adam Bakewell. Proc. 2000 Haskell Workshop. September 2001.<br />
<br />
==Pure type systems==<br />
<br />
;[http://research.microsoft.com/~simonpj/Papers/henk.ps.gz Henk: a typed intermediate language]<br />
:SL Peyton Jones and E Meijer, Proceedings of the Types in Compilation Workshop, Amsterdam, June 1997.<br />
<br />
;[http://www.cs.uu.nl/~johanj/MSc/jwroorda/ Pure Type Systems for Functional Programming]<br />
:Jan-Willem Roorda, Masters Thesis, University of Utrecht, INF/SCR-00-13, available online, 2000<br />
<br />
==Dependent Types==<br />
<br />
;[http://www.cs.nott.ac.uk/~txa/publ/ydtm.pdf Why Dependent Types Matter]<br />
:Thorsten Altenkirch and Conor McBride and James McKinna, Manuscript, available online, April, 2005. (Cited by 7)<br />
<br />
;[http://www.informatik.uni-bonn.de/~loeh/LambdaPi.html Simply Easy! An Implementation of a Dependently Typed Lambda Calculus]<br />
:Andres Löh, Conor McBride and Wouter Swierstra, 2007.<br />
<br />
==Unboxed values==<br />
<br />
;[http://www.soi.city.ac.uk/~ross/papers/pointed.html Parametricity and Unboxing with Unpointed Types]<br />
:John Launchbury and Ross Paterson, European Symposium on Programming, LNCS, vol. 1058, pp. 204-218, Springer, Linkping, Sweden, 1996.<br />
<br />
;[http://research.microsoft.com/~simonpj/Papers/unboxed-values.ps.Z Unboxed values as first class citizens]<br />
:SL Peyton Jones and J Launchbury, Functional Programming Languages and Computer Architecture (FPCA'91), Boston, LNCS 523, Springer Verlag, Sept 1991, pp636-666. (Cited by 105)<br />
<br />
==Modules==<br />
<br />
;[http://www.cse.ogi.edu/~diatchki/papers/modules98.pdf A Formal Specification of the Haskell 98 Module System]<br />
:Iavor S. Diatchki, Mark P. Jones, and Thomas Hallgren. Proceedings of the 2002 ACM SIGPLAN workshop on Haskell. Pittsburgh, Pennsylvania. 17 - 28 2002 ISBN 1-58113-605-6 (Cited by 12)<br />
<br />
;[http://research.microsoft.com/~simonpj/Papers/first-class-modules/index.htm First class modules for Haskell]<br />
:Mark Shields and Simon Peyton Jones; FOOL'02.<br />
<br />
;[http://research.microsoft.com/~simonpj/Papers/Nicklisch-modules.ps.gz An exploration of modular programs]<br />
:Electronic proceedings of the 1996 Glasgow Functional Programming Workshop, J Nicklisch and SL Peyton Jones, Ullapool, July 1996.<br />
<br />
==Exceptions==<br />
<br />
;[http://www.haskell.org/~simonmar/papers/ext-exceptions.pdf An Extensible Dynamically-Typed Hierarchy of Exceptions]<br />
:Simon Marlow. Haskell '06: Proceedings of the 2006 ACM SIGPLAN workshop on Haskell, Portland, Oregon, ACM Press, September 2006<br />
<br />
;[http://research.microsoft.com/~simonpj/Papers/imprecise-exn-sem.htm Imprecise Exceptions, Co-Inductively]<br />
:Andy Moran, Soeren Lassen, and Simon Peyton Jones. HOOTS'99.<br />
<br />
;[http://research.microsoft.com/~simonpj/Papers/imprecise-exn.htm A semantics for imprecise exceptions]<br />
:Simon Peyton Jones, Alastair Reid, Tony Hoare, Simon Marlow, Fergus Henderson. Proc Programming Language Design and Implementation (PLDI'99), Atlanta.<br />
<br />
;[http://research.microsoft.com/~simonpj/Papers/asynch-exns.htm Asynchronous exceptions in Haskell]<br />
:Simon Marlow, Simon Peyton Jones, Andy Moran and John Reppy, PLDI'01.<br />
<br />
;[http://www.reid-consulting-uk.ltd.uk/alastair/publications/except6.ps.gz Handling Exceptions in Haskell]<br />
:A. Reid, Research Report YALEU/DCS/RR-1175, Yale University, August, 1998<br />
<br />
==Lexically scoped type variables==<br />
<br />
;[http://research.microsoft.com/%7Esimonpj/papers/scoped%2Dtyvars/ Lexically scoped type variables]<br />
:Simon Peyton Jones and Mark Shields. 2004.<br />
<br />
==Records==<br />
<br />
;[http://research.microsoft.com/~simonpj/Papers/records.htm Lightweight Extensible Records for Haskell]<br />
:Mark Jones and Simon Peyton Jones, Haskell Workshop 1999.<br />
<br />
;[http://www.cs.uu.nl/~daan/download/papers/scopedlabels.pdf Extensible records with scoped labels]<br />
:Daan Leijen. The 2005 Symposium on Trends in Functional Programming (TFP'05), Tallin, Estonia, September 2005.<br />
<br />
;[http://www.cs.uu.nl/~daan/download/papers/fclabels.pdf First-class labels for extensible rows]<br />
:Daan Leijen. Technical Report UU-CS-2004-51, Departement of Computer Science, Universiteit Utrecht, 2004.<br />
<br />
;[http://www.reid-consulting-uk.ltd.uk/alastair/publications/h-wkshop95a/index.html Haskell Records]<br />
:J. Peterson, A. Reid, Proceedings of the Haskell Workshop, La Jolla, June 1995. <br />
<br />
;[http://www.cse.ogi.edu/~mpj/pubs/96-3.ps.gz A Polymorphic Type System for Extensible Records and Variants]<br />
:Benedict R. Gaster and Mark P. Jones. Department of Computer Science, University of Nottingham. Technical report NOTTCS-TR-96-3. November 1996.<br />
<br />
==Meta programming==<br />
<br />
;[http://research.microsoft.com/copyright/accept.asp?path=/users/simonpj/papers/dyntyping.ps.gz&pub=ACM Dynamic typing as staged type inference]<br />
:MB Shields, T Sheard, and SL Peyton Jones, POPL98.<br />
<br />
;[http://research.microsoft.com/~simonpj/Papers/meta-haskell/index.htm Template meta-programming for Haskell]<br />
:Tim Sheard and Simon Peyton Jones, Proceedings of the Haskell Workshop, Pittsburgh, 2002<br />
<br />
;[http://www.cse.unsw.edu.au/~chak/papers/SCK04.html Optimising Embedded DSLs using Template Haskell]<br />
:Sean Seefried, Manuel M. T. Chakravarty, and Gabriele Keller. In Gabor Karsai and Eelco Visser, editors, Third International Conference on Generative Programming and Component Engineering (GPCE'04), LNCS 3286, Springer-Verlag, pages 186-205, 2004. [An earlier draft was presented at the IFL 2003 - 15th International Workshop on the Implementation of Functional Languages, 2003.<br />
<br />
;[http://www.haskell.org/th/papers/Unrolling_and_Simplifying_Expressions_with_Template_Haskell.ps Unrolling and Simplifying Expressions with Template Haskell]<br />
:Ian Lynagh, May 2003.<br />
<br />
;[http://www.haskell.org/th/papers/hlpp.ps Automatic skeletons in Template Haskell]<br />
:Kevin Hammond, Jost Berthold and Rita Loogen, June 2003. Proceedings of 2003 Workshop on High Level Parallel Programming, Paris, France<br />
<br />
;[http://www.haskell.org/th/papers/Typing_Template_Haskell__Soft_Types.ps Typing Template Haskell: Soft Types]<br />
:Ian Lynagh, August 2004.<br />
<br />
==Dynamic typing==<br />
<br />
;[http://www.cs.uu.nl/groups/ST/stbib/swierstra-by-year/BaSw02.bib Typing dynamic typing]<br />
:A. I. Baars and S. D. Swierstra. In S. Peyton Jones, editor, Proceedings of the seventh ACM SIGPLAN international conference on Functional programming, pages 157--166. ACM Press, 2002<br />
<br />
==Parametricity==<br />
<br />
;[http://homepages.inf.ed.ac.uk/wadler/papers/free/free.ps.gz Theorems for free!]<br />
:Philip Wadler. 4'th International Conference on Functional Programming and Computer Architecture, London, September 1989.<br />
<br />
;[http://www.soi.city.ac.uk/~ross/papers/pointed.html Parametricity and Unboxing with Unpointed Types]<br />
:John Launchbury and Ross Paterson, European Symposium on Programming, LNCS, vol. 1058, pp. 204-218, Springer, Linkping, Sweden, 1996.<br />
<br />
;[http://wwwtcs.inf.tu-dresden.de/~voigt/seqFinal.pdf The Impact of seq on Free Theorems-Based Program Transformations]<br />
:Patricia Johann and Janis Voigtländer, Fundamenta Informaticae, vol. 69(1-2), pp. 63-102, 2006.<br />
<br />
;[http://wwwtcs.inf.tu-dresden.de/~voigt/TCS.pdf Selective strictness and parametricity in structural operational semantics, inequationally]<br />
:Janis Voigtländer and Patricia Johann, Theoretical Computer Science, vol. 388(1-3), pp. 290-318, 2007.<br />
<br />
;[http://wwwtcs.inf.tu-dresden.de/~voigt/pepm09-voigtlaender.pdf Proving Correctness via Free Theorems: The Case of the destroy/build-Rule]<br />
:Janis Voigtländer. Workshop on Partial Evaluation and Program Manipulation (PEPM'08), Proceedings, ACM Press, 2008.<br />
<br />
;[http://wwwtcs.inf.tu-dresden.de/~voigt/iandc.pdf A family of syntactic logical relations for the semantics of Haskell-like languages]<br />
:Patricia Johann and Janis Voigtländer, Information and Computation, vol. 207(2), pp. 341-368, 2009.<br />
<br />
;[http://wwwtcs.inf.tu-dresden.de/~voigt/tlca09.pdf Parametricity for Haskell with Imprecise Error Semantics]<br />
:Florian Stenger and Janis Voigtländer. International Conference on Typed Lambda Calculi and Applications (TLCA'09), Proceedings, Springer-Verlag, 2009.<br />
<br />
<br />
==Type classes==<br />
<br />
;[http://homepages.inf.ed.ac.uk/wadler/papers/class/class.ps.gz How to make ad-hoc polymorphism less ad hoc]<br />
:Philip Wadler and Stephen Blott. 16'th Symposium on Principles of Programming Languages, ACM Press, Austin, Texas, January 1989.<br />
<br />
;[http://research.microsoft.com/~simonpj/Papers/classhask.ps.gz Type classes in Haskell, CV Hall, K Hammond, SL Peyton Jones, and PL Wadler]<br />
:European Symposium On Programming, LNCS 788, Springer Verlag, pp. 241-256, April 1994. (Cited by 131)<br />
<br />
;[http://www.cse.ogi.edu/~mpj/pubs/pldi93.html Implementing Type Classes]<br />
:John Peterson and Mark P. Jones, In Proceedings of ACM SIGPLAN Symposium on Programming Language Design and Implementation, ACM SIGPLAN, June 1993. (Cited by 40)<br />
<br />
;[http://www.cs.chalmers.se/pub/cs-reports/papers/overload-fpca-93.ps.Z Implementing Haskell overloading]<br />
:Lennart Augustsson, 1993. FPCA. 65-73<br />
<br />
;[http://web.cecs.pdx.edu/~mpj/pubs/springschool.html Functional Programming with Overloading and Higher-Order Polymorphism]<br />
:Mark P. Jones, First International Spring School on Advanced Functional Programming Techniques, Baastad, Sweden, Springer-Verlag Lecture Notes in Computer Science 925, May 1995.<br />
<br />
;[http://research.microsoft.com/~simonpj/Papers/type-class-design-space Type classes: exploring the design space]<br />
:Simon Peyton Jones, Mark Jones, Erik Meijer, Haskell Workshop 1997.<br />
<br />
;[http://www.cse.ogi.edu/~mpj/pubs/fpca93.html A system of constructor classes: overloading and implicit higher-order polymorphism]<br />
:Mark P. Jones, In FPCA '93: Conference on Functional Programming Languages and Computer Architecture, Copenhagen, Denmark, June 1993.<br />
<br />
;[http://homepages.inf.ed.ac.uk/wadler/papers/overload2/overload2.ps.gz A second look at overloading]<br />
:Martin Odersky, Philip Wadler, Martin Wehr. 7'th International Conference on Functional Programming and Computer Architecture, ACM Press, San Diego, California, June 1995.<br />
<br />
;[http://citeseer.ist.psu.edu/laufer94combining.html Combining Type Classes and Existential Types]<br />
:Konstantin Laufer, Proceedings of the Latin American Informatic Conference (PANEL), 1994<br />
<br />
;[http://citeseer.ist.psu.edu/aufer95type.html Type Classes with Existential Types]<br />
:Konstantin Laufer, Journal of Functional Programming, 1996, May<br />
<br />
;[http://www.cse.unsw.edu.au/~chak/papers/DHCK06.html Modular Type Classes]<br />
:Derek Dreyer, Robert Harper, Manuel M.T. Chakravarty and Gabriele Keller, 2006<br />
<br />
;[http://www.informatik.uni-bonn.de/~ralf/hw2001/4.pdf Named instances for Haskell type classes]<br />
:W Kahl, J Scheffczyk - Proc. Haskell Workshop, 2001 (Cited by 12)<br />
<br />
===Deriving type classes===<br />
<br />
;[http://research.microsoft.com/~simonpj/Papers/derive.htm Derivable Type classes] <br />
:Ralf Hinze and Simon Peyton Jones, Haskell Workshop 2000.<br />
<br />
;[http://www.cis.upenn.edu/~sweirich/RepLib/ RepLib: A Library for Derivable Type Classes]<br />
:Stephanie Weirich 2006<br />
<br />
===Applications of type classes===<br />
<br />
;[http://okmij.org/ftp/Haskell/number-parameterized-types.html Number-parameterized types]<br />
:Oleg Kiselyov, The Monad.Reader. IssueFive. Oct 2nd, 2005<br />
<br />
;[http://web.comlab.ox.ac.uk/oucl/work/jeremy.gibbons/publications/typecase.pdf TypeCase: a design pattern for type-indexed functions]<br />
:Bruno C. d. S. Oliveira, Jeremy Gibbons. Proceedings of the 2005 ACM SIGPLAN workshop on Haskell. Tallinn, Estonia. 98 - 109, 2005 ISBN:1-59593-071-X<br />
<br />
;[http://okmij.org/ftp/Haskell/types.html#Prepose Functional pearl: implicit configurations--or, type classes reflect the values of types]<br />
:Oleg Kiselyov, Chung-chieh Shan, Proceedings of the 2004 ACM SIGPLAN workshop on Haskell, Snowbird, Utah, USA, 2004 ISBN 1-58113-850-4<br />
<br />
;[http://www.comp.nus.edu.sg/~sulzmann/publications/extract-typeclassproofs.pdf Extracting Programs from Type Class Proofs]<br />
:Martin Sulzmann, 2006<br />
<br />
;[http://www.comp.nus.edu.sg/~sulzmann/manuscript/coind-type-class-proofs.ps Co-induction and Type Improvement in Type Class Proofs]<br />
:Martin Sulzmann, Jeremy Wazny and Peter J. Stuckey. 2005<br />
<br />
;[http://www.cs.nott.ac.uk/~ctm/faking.ps.gz Faking It (Simulating Dependent Types in Haskell)]<br />
:Conor McBride, Journal of Functional Programming, 12(4&5):375-392, July 2002<br />
<br />
;[http://www.comp.nus.edu.sg/~sulzmann/manuscript/aophaskell.ps.gz Aspect-Oriented Programming with Type Classes]<br />
:Martin Sulzmann and Meng Wang, 2006.<br />
<br />
;[http://wwwtcs.inf.tu-dresden.de/~voigt/mpc08.pdf Asymptotic Improvement of Computations over Free Monads]<br />
:Janis Voigtländer. Mathematics of Program Construction (MPC'08), Proceedings, LNCS 5133:388-403, Springer-Verlag, 2008.<br />
<br />
<br />
==Undecidable instances==<br />
<br />
;[http://www.haskell.org/ghc/docs/6.4.2/html/users_guide/type-extensions.html#undecidable-instances Undecidable instances]<br />
:GHC User's Guide.<br />
<br />
==Multi-parameter type classes==<br />
<br />
;[http://www.comp.nus.edu.sg/~sulzmann/publications/ghc-mptc-inf.ps Principal Type Inference for GHC-Style Multi-Parameter Type Classes]<br />
:Martin Sulzmann, Tom Schrijvers and Peter J. Stuckey. In APLAS'06.<br />
<br />
;[http://www.comp.nus.edu.sg/~sulzmann/manuscript/mptc-inf-old.pdf Type Inference for Multi-Parameter Type Classes]<br />
:Martin Sulzmann and Peter J. Stuckey. 2005<br />
<br />
;[http://ostrich.lcs.mit.edu/cgi-bin/pickbib?jfp::DugganO2002 Type-checking multi-parameter type classes]<br />
:Dominic Duggan and John Ophel, Journal of Functional Programming, 12(2):133-158, March 2002<br />
<br />
==Functional dependencies==<br />
<br />
;[http://www.cse.ogi.edu/~mpj/pubs/fundeps.html Type Classes with Functional Dependencies]<br />
:Mark P. Jones, In Proceedings of the 9th European Symposium on Programming, ESOP 2000, Berlin, Germany, March 2000, Springer-Verlag LNCS 1782.<br />
<br />
;[http://research.microsoft.com/~simonpj/Papers/fd-chr/index.htm Sound and Decidable Type Inference for Functional Dependencies]<br />
:Gregory J. Duck, Simon Peyton Jones, Peter J. Stuckey, and Martin Sulzmann, European Symposium on Programming 2004 (ESOP'04).<br />
<br />
;[http://www.comp.nus.edu.sg/~sulzmann/publications/jfp-fds-revised.pdf Understanding Functional Dependencies via Constraint Handling Rules]<br />
:Martin Sulzmann, Gregory J. Duck, Simon Peyton-Jones and Peter J. Stuckey.j To appear in Journal of Functional Programming. 2006<br />
<br />
;[http://www.comp.nus.edu.sg/~sulzmann/manuscript/afds.ps Associated Functional Dependencies]<br />
:Martin Sulzmann and Edmund Soon Lee Lam. 2005<br />
<br />
==Constraint Handling Rules==<br />
<br />
;[http://www.comp.nus.edu.sg/~sulzmann/publications/aplas06-invited.pdf Type Processing by Constraint Reasoning]<br />
:Peter J. Stuckey, Martin Sulzmann and Jeremy Wazny, In APLAS'06.<br />
<br />
;[http://www.comp.nus.edu.sg/~sulzmann/manuscript/chr-stm.ps A Concurrent Constraint Handling Rules Implementation in Haskell with Software Transactional Memory]<br />
:Edmund S.L. Lam and Martin Sulzmann<br />
<br />
;[http://www.comp.nus.edu.sg/~sulzmann/publications/chr06-observable.ps Observable Confluence for Constraint Handling Rules]<br />
:Gregory J. Duck, Peter J. Stuckey and Martin Sulzmann<br />
<br />
==Generalised Algebraic Data Types (GADTs)==<br />
<br />
;[http://research.microsoft.com/~simonpj/papers/gadt/index.htm Simple unification-based type inference for GADTs]<br />
:Simon Peyton Jones, Dimitrios Vytiniotis, Stephanie Weirich, and Geoffrey Washburn. Submitted to PLDI 2005<br />
<br />
;[http://www.cis.upenn.edu/~geoffw/research/papers/MS-CIS-05-26.pdf Wobbly types: type inference for generalised algebraic data types]<br />
:S Peyton Jones, G. Washburn, and S. Weirich. 2004.<br />
<br />
;[http://www.comp.nus.edu.sg/~sulzmann/manuscript/simple-translate-gadts.ps Translating Generalized Algebraic Data Types to System F]<br />
:Martin Sulzmann and Meng Wang. 2005<br />
<br />
;[http://cristal.inria.fr/~fpottier/publis/pottier-regis-gianas-05.pdf Stratified type inference for generalized algebraic data types]<br />
:François Pottier and Yann Régis-Gianas, 2006<br />
<br />
;[http://www.comp.nus.edu.sg/~sulzmann/manuscript/gadt-short.ps Type Inference for GADTs via Herbrand Constraint Abduction]<br />
:Martin Sulzmann, Tom Schrijvers and Peter J. Stuckey, 2006 <br />
<br />
;[http://www.comp.nus.edu.sg/~sulzmann/publications/tr-eadt.ps.gz A Framework for Extended Algebraic Data Types]<br />
:Martin Sulzmann, Jeremy Wazny and Peter J. Stuckey, 2006<br />
<br />
;[http://www.cs.kuleuven.be/~toms/Research/papers/implication_constraints.pdf Complete and Decidable Type Inference for GADTs]<br />
:Tom Schrijvers, Simon Peyton-Jones, Martin Sulzmann and Dimitrios Vytiniotis, 2009.<br />
<br />
See also the [[GADT]] page.<br />
<br />
==Parametric Regular Data Types==<br />
<br />
;[http://www.comp.nus.edu.sg/~sulzmann/manuscript/parametric-regular.ps Type Inference and Compilation for Parametric Regular Data Types]<br />
:Martin Sulzmann and Kenny Zhuo Ming Lu, 2006<br />
<br />
;[http://www.comp.nus.edu.sg/~sulzmann/manuscript/haskell-xduce.ps The Marriage of Haskell and XDuce]<br />
:Martin Sulzmann and Kenny Zhuo Ming Lu<br />
<br />
==Type Families and Associated types==<br />
<br />
;[http://www.haskell.org/~simonmar/papers/assoc.pdf Associated types with class]<br />
:Manuel M. T. Chakravarty, Gabriele Keller, Simon Peyton Jones, Simon Marlow) POPL '05: Proceedings of the 32nd ACM SIGPLAN-SIGACT sysposium on Principles of programming languages, pages 1--13, Long Beach, California, USA, ACM Press, 2005<br />
<br />
;[http://www.cse.unsw.edu.au/~chak/papers/CKP05.html Associated Type Synonyms]<br />
:Manuel M. T. Chakravarty, Gabriele Keller, and Simon Peyton Jones. In Proceedings of The Tenth ACM SIGPLAN International Conference on Functional Programming, ACM Press, pages 241-253, 2005.<br />
<br />
;[http://www.informatik.uni-freiburg.de/~wehr/diplom ML Modules and Haskell Type Classes: A Constructive Comparison]<br />
:Stefan Wehr Diplomarbeit. Albert-Ludwigs-Universitt Freiburg, Fakultt fr Angewandte Wissenschaften, Institut fr Informatik, November 2005. <br />
<br />
;[http://www.cse.unsw.edu.au/~chak/papers/SCP06.html System F with Type Equality Coercions]<br />
:Martin Sulzmann, Manuel M. T. Chakravarty, and Simon Peyton Jones.<br />
<br />
;[http://www.cs.kuleuven.be/~toms/Research/papers/type_functions.pdf Towards Open Type Functions for Haskell]<br />
:Tom Schrijvers, Simon Peyton Jones, Martin Sulzmann, and Manuel Chakravarty. In Proceedings of IFL' 07, Freiburg, Germany, 2007.<br />
<br />
;[http://www.cs.kuleuven.be/~toms/Research/papers/draft_type_functions_2008.pdf Type Checking with Open Type Functions for Haskell]<br />
:Tom Schrijvers, Simon Peyton Jones, Manuel Chakravarty, and Martin Sulzmann. In Proceedings of ICFP' 08, Victoria, Canada, 2008.<br />
<br />
<br />
==Arbitrary-rank polymorphism==<br />
<br />
;[http://www.ubka.uni-karlsruhe.de/vvv/1996/informatik/81/81.pdf.gz Putting type annotations to work]<br />
:Martin Odersky and Konstantin Läufer. Proceedings of the 23rd ACM SIGPLAN-SIGACT symposium on Principles of programming languages. St. Petersburg Beach, Florida, United States. 54 - 67 1996 ISBN 0-89791-769-3<br />
<br />
;[http://journals.cambridge.org/production/action/cjoGetFulltext%3Ffulltextid%3D445910 Practical type inference for arbitrary-rank types]<br />
:SP Jones, M Shields - Submitted to the Journal of Functional Programming, 2005<br />
<br />
==Phantom types==<br />
<br />
;[http://techreports.library.cornell.edu:8081/Dienst/UI/1.0/Display/cul.cis/TR2003-1901 First-class phantom types]<br />
:James Cheney and Ralf Hinze. Technical Report TR2003-1901, Cornell University, 2003.<br />
<br />
;[http://ttic.uchicago.edu/~fluet/research/phantom-subtyping/jfp06/jfp06.pdf Phantom Types and Subtyping]<br />
:Matthew Fluet and Riccardo Pucella. Submitted to the Journal of Functional Programming, 2006.<br />
<br />
==Implicit parameters==<br />
<br />
;[http://www.cse.ogi.edu/~mbs/pub/implicit_parameters/implicit.ps Implicit Parameters: Dynamic Scoping with Static Types]<br />
:Jeffrey Lewis, Mark Shields, Erik Meijer and John Launchbury. POPL'00. 2000.<br />
<br />
;[http://www.cs.chalmers.se/~rjmh/Globals.ps Global variables in Haskell]<br />
:John Hughes. J. Funct. Program. 14(5): 489-502 (2004) <br />
<br />
;[http://www.cs.uu.nl/pub/RUU/CS/techreps/CS-2004/2004-059.pdf Explicit Implicit Parameters]<br />
:A. Dijkstra and S. D. Swierstra. UU-CS 2004-059, 2004.<br />
<br />
==Object oriented Haskell==<br />
<br />
;[http://research.microsoft.com/~simonpj/Papers/oo-haskell/index.htm Object-Oriented Style Overloading for Haskell] <br />
:Mark Shields and Simon Peyton Jones; BABEL workshop '01.<br />
<br />
;[http://www.cse.unsw.edu.au/~chak/papers/PC03.html Interfacing Haskell with Object-Oriented Languages]<br />
:Andr T. H. Pang and Manuel M. T. Chakravarty. In Greg Michaelson and Phil Trinder, editors, Implementation of Functional Languages: 15th International Workshop, IFL 2003, Edinburgh, UK, September 8-11, 2003, Revised Papers, LNCS 3145, Springer-Verlag, pages 20-36, 2004. <br />
<br />
;[http://citeseer.ist.psu.edu/118134.html Haskell++: An Object-Oriented Extension of Haskell]<br />
:Jan Sparud and John Hughes. Haskell Workshop 1995<br />
<br />
;[http://homepages.cwi.nl/~ralf/OOHaskell/ Haskell's overlooked object system]<br />
:Oleg Kiselyov and Ralf Lämmel, submitted for journal publication; online since 30 Sep. 2004;<br />
<br />
==Restricted Datatypes==<br />
<br />
;[http://www.cs.chalmers.se/~rjmh/Papers/restricted-datatypes.ps Restricted datatypes]<br />
:John Hughes. 1999 Haskell workshop<br />
<br />
==Patterns==<br />
<br />
;[http://www.cs.yale.edu/homes/tullsen/patterns.ps First Class Patterns]<br />
:Mark Tullsen. Practical Aspects of Declarative Languages, Second International Workshop, PADL 2000. volume 1753 of Lecture Notes in Computer Science. January 2000. <br />
<br />
===Pattern guards===<br />
<br />
;[http://research.microsoft.com/~simonpj/Papers/pat.htm Pattern Guards and Transformational Patterns]<br />
:Martin Erwig and Simon Peyton Jones; Haskell Workshop 2000.<br />
<br />
;[http://research.microsoft.com/Users/simonpj/Haskell/guards.html A new view of guards]<br />
:Simon Peyton Jones, April 1997<br />
<br />
===Views===<br />
<br />
;[http://www.haskell.org/development/views.html Views: An Extension to Haskell Pattern Matching]<br />
:Warren Burton, Erik Meijer, Patrick Sansom, Simon Thompson and Phil Wadler.<br />
<br />
;[http://homepages.inf.ed.ac.uk/wadler/papers/view/view.ps.gz Views: A way for pattern matching to cohabit with data abstraction]<br />
:POPL 14 (1987), 307-313.<br />
<br />
==Qualified types==<br />
<br />
;[http://haskell.readscheme.org/servlets/cite.ss?pattern=mpj-jones1994a Qualified Types: Theory and Practice]<br />
:Mark P. Jones. PhD. Thesis. Yale University. November 1994.<br />
<br />
;[http://www.cse.ogi.edu/~mpj/pubs/fpca95.ps Simplifying and Improving Qualified Types]<br />
:Mark P. Jones. FPCA '95: Conference on Functional Programming Languages and Computer Architecture. June 1995.<br />
<br />
;[http://www.cse.ogi.edu/~mpj/pubs/RR-1040.ps Simplifying and Improving Qualified Types]<br />
:Mark P. Jones. Yale University. Research Report YALEU/DCS/RR-1040. June 1994.<br />
<br />
;[http://www.cse.ogi.edu/~mpj/pubs/RR-989.ps Coherence for qualified types]<br />
:Mark P. Jones. Yale University. Research Report YALEU/DCS/RR-989. September 1993. <br />
<br />
;[http://www.cse.ogi.edu/~mpj/pubs/rev-qual-types.ps A theory of qualified types]<br />
:Mark P. Jones. ESOP '92: European Symposium on Programming. Lecture Notes in Computer Science, 582. February 1992. (Cited by 68)<br />
<br />
==Polymorphic recursion==<br />
<br />
;[http://portal.acm.org/citation.cfm%3Fcoll%3DGUIDE%26dl%3DGUIDE%26id%3D169692 Type inference with polymorphic recursion]<br />
:F Henglein - ACM Transactions on Programming Languages and Systems (1993)<br />
<br />
;[http://www.jucs.org/jucs_9_8/practical_type_inference_for/paper.pdf Practical Type Inference for Polymorphic Recursion: an Implementation in Haskell]<br />
:C Vasconcellos, L Figueiredo, C Camarao - Journal of Universal Computer Science, 2003<br />
<br />
;[http://www.dcc.ufmg.br/~camarao/ml0-impl.ps Type Inference for Polymorphic Recursive Definitions: a Specification in Haskell]<br />
:L Figueiredo, C Camarao<br />
<br />
[[Category:Research]]<br />
[[Category:Type-level programming]]</div>Tschrijvershttps://wiki.haskell.org/index.php?title=Simonpj/Talk:FunWithTypeFuns&diff=28212Simonpj/Talk:FunWithTypeFuns2009-05-15T11:11:40Z<p>Tschrijvers: </p>
<hr />
<div>= Fun with Type Functions =<br />
<br />
Oleg Kiselyov, Ken Shan, and Simon Peyton Jones have a draft paper<br />
* '''[http://research.microsoft.com/~simonpj/papers/assoc-types/typefun.pdf Fun With Type Functions]'''<br />
which will appear in the proceedings of Tony Hoare's 75th birthday celebration.<br />
<blockquote><br />
'''Abstract'''. Tony Hoare has always been a leader in writing down and proving<br />
properties of programs. To prove properties of programs automatically,<br />
the most widely used technology today is by far the ubiquitous type checker.<br />
Alas, static type systems inevitably exclude some good programs<br />
and allow some bad ones. This dilemma motivates us to describe some fun we've<br />
been having with Haskell, by making the type system more expressive<br />
without losing the benefits of automatic proof and compact expression.<br />
<p><br />
Haskell's type system extends Hindley-Milner with two distinctive<br />
features: polymorphism over type constructors and overloading<br />
using type classes. These features have been integral to Haskell<br />
since its beginning, and they are widely used and appreciated. More recently, Haskell has been enriched with<br />
''type families'', or ''associated types'', <br />
which allows functions on types to be<br />
expressed as straightforwardly as functions on values. This facility<br />
makes it easier for programmers to effectively extend the compiler by<br />
writing functional programs that execute during type-checking.<br />
</p><p><br />
This paper gives a programmer's tour of type families as they are<br />
supported in GHC today.<br />
</p></blockquote><br />
<br />
This Wiki page is a discussion page for the paper. If you are kind enough to read this paper, please help us by jotting down any thoughts it triggers off. Things to think about:<br />
* What is unclear?<br />
* What is omitted that you'd like to see?<br />
* Do you have any cool examples that are of a somewhat different character than the ones we describe? (If so, do explain the example on this page!)<br />
<br />
Deadline is sometime in June 2009.<br />
<br />
You can identify your entries by preceding them with four tildes. Doing so adds your name, and the date. Thus:<br />
<br />
:[[User:Simonpj|Simonpj]] 08:42, 19 April 2007 (UTC) Note from Simon<br />
<br />
<br />
If you say who you are in this way, we'll be able to acknowledge your help in a revised version of the paper.<br />
<br />
------------------------<br />
Add comments here (newest at the top):<br />
<br />
[[User:bjpop|BerniePope]] 06:18, Fri 15 May 2009 (UTC) Typo in Appendix B.<br />
<br />
"GHC should noat" -> "GHC should not"<br />
<br />
[[User:Tanimoto|tanimoto]] 02:17, 15 May 2009 (UTC) Typo in references<br />
<br />
In reference [32], page 30, Oleg's last name is misspelled as "Kiselov".<br />
<br />
<br />
[[User:Ryani|Ryani]] 23:01, 14 May 2009 (UTC) Fun paper! Comments:<br />
<br />
I was writing a generic finite map a while ago and determined that the generic memoized trie was better in almost all cases; it was simpler semantically and didn't have a significant performance difference. Then you have "type Map k v = Table k (Maybe v)". Is it worth calling out this special case in its own section?<br />
<br />
Also, in respose to ChrisKuklewicz, I think the type for "cons" is correct, but perhaps one instance should be given as an example.<br />
<br />
[[User:Dave Menendez|Dave Menendez]] 16:52, 14 May 2009 (UTC) On page 11, you refer to a "specialised instance for Table Int that uses some custom <br />
(but inﬁnite!) tree representation for Int." Was this meant to be Integer? Surely any tree representation for Int would be large but finite. <br />
<br />
-------------------<br />
Peter Verswyvelen and I have been working on some type family fun to give us generalised partial application (even to the point of being able to cope with giving arguments, but not a function). I don't know if it really makes any interesting point that you didn't already in the paper, but it's certainly fun...<br />
<br />
<haskell><br />
{-# LANGUAGE TypeFamilies, EmptyDataDecls, TypeOperators, FlexibleInstances, FlexibleContexts #-}<br />
<br />
module Burn2 where<br />
<br />
newtype V a = V a -- A value<br />
data B a = B -- A value we don't want to provide yet<br />
<br />
-- Type level homogenous lists (well just tuples in a list-like syntax really)<br />
data Nil a = Nil<br />
data a :& b = !a :& !b<br />
<br />
infixr 5 :& <br />
<br />
class Apply funargs where<br />
type Result funargs :: *<br />
apply :: funargs -> Result funargs<br />
<br />
instance (Apply (V b :& rest), a ~ c) => Apply (V (a->b) :& V c :& rest) where<br />
type Result (V (a->b) :& V c :& rest) = Result (V b :& rest)<br />
apply (V f :& V a :& rest) = apply $ V (f a) :& rest<br />
<br />
instance (Apply (V b :& rest), a ~ c) => Apply (B (a->b) :& V c :& rest) where<br />
type Result (B (a->b) :& V c :& rest) = (a->b) -> Result (V b :& rest)<br />
apply (B :& V a :& rest) = \f -> apply $ V (f a) :& rest<br />
<br />
instance (Apply (V b :& rest), a ~ c) => Apply (V (a->b) :& B c :& rest) where<br />
type Result (V (a->b) :& B c :& rest) = a -> Result (V b :& rest)<br />
apply (V f :& B :& rest) = \a -> apply $ V (f a) :& rest<br />
<br />
instance (Apply (V b :& rest), a ~ c) => Apply (B (a->b) :& B c :& rest) where<br />
type Result (B (a->b) :& B c :& rest) = (a->b) -> a -> Result (V b :& rest)<br />
apply (B :& B :& rest) = \f a -> apply $ V (f a) :& rest<br />
<br />
instance Apply (V a :& Nil b) where<br />
type Result (V a :& Nil b) = a<br />
apply (V a :& Nil) = a<br />
<br />
instance Apply (B a :& Nil b) where<br />
type Result (B a :& Nil b) = B a<br />
apply (B :& Nil) = B<br />
<br />
v1 = apply (V 1 :& Nil)<br />
f1 = apply (B :& Nil)<br />
v2 = apply (V negate :& V 1 :& Nil)<br />
f3 = apply (V negate :& B :& Nil)<br />
v3 = apply (V f3 :& V 1 :& Nil)<br />
</haskell><br />
<br />
[[User:Beelsebob|Beelsebob]] 13:04, 14 May 2009 (UTC)<br />
<br />
<br />
--------------------------------------<br />
<br />
End of section 2.2, I think "cons :: a -> [b] -> [ResTy a b]" should be "cons :: a -> [b] -> ResTy a b"<br />
<br />
[[User:ChrisKuklewicz|ChrisKuklewicz]] 15:28, 14 May 2009 (UTC)<br />
<br />
<br />
--------------------------------------<br />
<br />
End of page 19 with footnote 9. I could not simply copy and paste the URL because of a stray space after the '-' in http://okmij.org/ftp/Haskell/keyword- arguments.lhs<br />
<br />
[[User:ChrisKuklewicz|ChrisKuklewicz]] 16:08, 14 May 2009 (UTC)<br />
<br />
--------------------------------------<br />
<br />
Typo "Mounier" --> "Monnier"<br />
<br />
[[User:Tschrijvers|Tom Schrijvers]] 11:11, 15 May 2009 (UTC)</div>Tschrijvershttps://wiki.haskell.org/index.php?title=Research_papers/Type_systems&diff=23017Research papers/Type systems2008-09-20T13:14:05Z<p>Tschrijvers: added ICFP 2008 paper on open type functions</p>
<hr />
<div>__TOC__<br />
<br />
==Haskell semantics==<br />
<br />
;[http://research.microsoft.com/~simonpj/Papers/static-semantics.dvi.gz A static semantics for Haskell]<br />
:SL Peyton Jones and PL Wadler, (draft), Department of Computing Science, University of Glasgow, 1992. (Cited by 20)<br />
<br />
;[http://haskell.org/onlinereport/dynamic-semantics.dvi.gz A Dynamic Semantics for Haskell] <br />
:Kevin Hammond and Cordelia Hall, (draft), University of Glasgow, 1992, 23 pages.<br />
<br />
;[http://citeseer.ist.psu.edu/424440.html Typing Haskell in Haskell] <br />
:Mark P. Jones, In Proceedings of the 1999 Haskell Workshop, Paris, France, October 1999. Published in Technical Report UU-CS-1999-28, Department of Computer Science, University of Utrecht. (Cited by 66)<br />
<br />
;[http://www.pms.informatik.uni-muenchen.de/mitarbeiter/panne/haskell_libs/hsparser.html HParser]<br />
:A parser for Haskell written purely in Haskell (using the Happy parser generator).<br />
<br />
;[http://www.cse.ogi.edu/~hallgren/Talks/LHiH/ A Lexer for Haskell in Haskell]<br />
:Thomas Hallgren, PacSoft Oregon Graduate Institute, 14 January, 2002<br />
<br />
;[http://citeseer.ist.psu.edu/launchbury93natural.html A Natural Semantics for Lazy Evaluation]<br />
:John Launchbury, Conference Record of the Twentieth Annual ACM SIGPLAN-SIGACT Symposium on Principles of Programming Languages, Charleston, South Carolina, 144--154, 1993.<br />
<br />
;[http://www.cs.nott.ac.uk/~gmh/papers/11.ps A Space Semantics for Core Haskell]<br />
:Adam Bakewell. Proc. 2000 Haskell Workshop. September 2001.<br />
<br />
==Pure type systems==<br />
<br />
;[http://research.microsoft.com/~simonpj/Papers/henk.ps.gz Henk: a typed intermediate language]<br />
:SL Peyton Jones and E Meijer, Proceedings of the Types in Compilation Workshop, Amsterdam, June 1997.<br />
<br />
;[http://www.cs.uu.nl/~johanj/MSc/jwroorda/ Pure Type Systems for Functional Programming]<br />
:Jan-Willem Roorda, Masters Thesis, University of Utrecht, INF/SCR-00-13, available online, 2000<br />
<br />
==Dependent Types==<br />
<br />
;[http://www.cs.nott.ac.uk/~txa/publ/ydtm.pdf Why Dependent Types Matter]<br />
:Thorsten Altenkirch and Conor McBride and James McKinna, Manuscript, available online, April, 2005. (Cited by 7)<br />
<br />
;[http://www.informatik.uni-bonn.de/~loeh/LambdaPi.html Simply Easy! An Implementation of a Dependently Typed Lambda Calculus]<br />
:Andres Löh, Conor McBride and Wouter Swierstra, 2007.<br />
<br />
==Unboxed values==<br />
<br />
;[http://www.soi.city.ac.uk/~ross/papers/pointed.html Parametricity and Unboxing with Unpointed Types]<br />
:John Launchbury and Ross Paterson, European Symposium on Programming, LNCS, vol. 1058, pp. 204-218, Springer, Linkping, Sweden, 1996.<br />
<br />
;[http://research.microsoft.com/~simonpj/Papers/unboxed-values.ps.Z Unboxed values as first class citizens]<br />
:SL Peyton Jones and J Launchbury, Functional Programming Languages and Computer Architecture (FPCA'91), Boston, LNCS 523, Springer Verlag, Sept 1991, pp636-666. (Cited by 105)<br />
<br />
==Modules==<br />
<br />
;[http://www.cse.ogi.edu/~diatchki/papers/modules98.pdf A Formal Specification of the Haskell 98 Module System]<br />
:Iavor S. Diatchki, Mark P. Jones, and Thomas Hallgren. Proceedings of the 2002 ACM SIGPLAN workshop on Haskell. Pittsburgh, Pennsylvania. 17 - 28 2002 ISBN 1-58113-605-6 (Cited by 12)<br />
<br />
;[http://research.microsoft.com/~simonpj/Papers/first-class-modules/index.htm First class modules for Haskell]<br />
:Mark Shields and Simon Peyton Jones; FOOL'02.<br />
<br />
;[http://research.microsoft.com/~simonpj/Papers/Nicklisch-modules.ps.gz An exploration of modular programs]<br />
:Electronic proceedings of the 1996 Glasgow Functional Programming Workshop, J Nicklisch and SL Peyton Jones, Ullapool, July 1996.<br />
<br />
==Exceptions==<br />
<br />
;[http://www.haskell.org/~simonmar/papers/ext-exceptions.pdf An Extensible Dynamically-Typed Hierarchy of Exceptions]<br />
:Simon Marlow. Haskell '06: Proceedings of the 2006 ACM SIGPLAN workshop on Haskell, Portland, Oregon, ACM Press, September 2006<br />
<br />
;[http://research.microsoft.com/~simonpj/Papers/imprecise-exn-sem.htm Imprecise Exceptions, Co-Inductively]<br />
:Andy Moran, Soeren Lassen, and Simon Peyton Jones. HOOTS'99.<br />
<br />
;[http://research.microsoft.com/~simonpj/Papers/imprecise-exn.htm A semantics for imprecise exceptions]<br />
:Simon Peyton Jones, Alastair Reid, Tony Hoare, Simon Marlow, Fergus Henderson. Proc Programming Language Design and Implementation (PLDI'99), Atlanta.<br />
<br />
;[http://research.microsoft.com/~simonpj/Papers/asynch-exns.htm Asynchronous exceptions in Haskell]<br />
:Simon Marlow, Simon Peyton Jones, Andy Moran and John Reppy, PLDI'01.<br />
<br />
;[http://www.reid-consulting-uk.ltd.uk/alastair/publications/except6.ps.gz Handling Exceptions in Haskell]<br />
:A. Reid, Research Report YALEU/DCS/RR-1175, Yale University, August, 1998<br />
<br />
==Lexically scoped type variables==<br />
<br />
;[http://research.microsoft.com/%7Esimonpj/papers/scoped%2Dtyvars/ Lexically scoped type variables]<br />
:Simon Peyton Jones and Mark Shields. 2004.<br />
<br />
==Records==<br />
<br />
;[http://research.microsoft.com/~simonpj/Papers/records.htm Lightweight Extensible Records for Haskell]<br />
:Mark Jones and Simon Peyton Jones, Haskell Workshop 1999.<br />
<br />
;[http://www.cs.uu.nl/~daan/download/papers/scopedlabels.pdf Extensible records with scoped labels]<br />
:Daan Leijen. The 2005 Symposium on Trends in Functional Programming (TFP'05), Tallin, Estonia, September 2005.<br />
<br />
;[http://www.cs.uu.nl/~daan/download/papers/fclabels.pdf First-class labels for extensible rows]<br />
:Daan Leijen. Technical Report UU-CS-2004-51, Departement of Computer Science, Universiteit Utrecht, 2004.<br />
<br />
;[http://www.reid-consulting-uk.ltd.uk/alastair/publications/h-wkshop95a/index.html Haskell Records]<br />
:J. Peterson, A. Reid, Proceedings of the Haskell Workshop, La Jolla, June 1995. <br />
<br />
;[http://www.cse.ogi.edu/~mpj/pubs/96-3.ps.gz A Polymorphic Type System for Extensible Records and Variants]<br />
:Benedict R. Gaster and Mark P. Jones. Department of Computer Science, University of Nottingham. Technical report NOTTCS-TR-96-3. November 1996.<br />
<br />
==Meta programming==<br />
<br />
;[http://research.microsoft.com/copyright/accept.asp?path=/users/simonpj/papers/dyntyping.ps.gz&pub=ACM Dynamic typing as staged type inference]<br />
:MB Shields, T Sheard, and SL Peyton Jones, POPL98.<br />
<br />
;[http://research.microsoft.com/~simonpj/Papers/meta-haskell/index.htm Template meta-programming for Haskell]<br />
:Tim Sheard and Simon Peyton Jones, Proceedings of the Haskell Workshop, Pittsburgh, 2002<br />
<br />
;[http://www.cse.unsw.edu.au/~chak/papers/SCK04.html Optimising Embedded DSLs using Template Haskell]<br />
:Sean Seefried, Manuel M. T. Chakravarty, and Gabriele Keller. In Gabor Karsai and Eelco Visser, editors, Third International Conference on Generative Programming and Component Engineering (GPCE'04), LNCS 3286, Springer-Verlag, pages 186-205, 2004. [An earlier draft was presented at the IFL 2003 - 15th International Workshop on the Implementation of Functional Languages, 2003.<br />
<br />
;[http://www.haskell.org/th/papers/Unrolling_and_Simplifying_Expressions_with_Template_Haskell.ps Unrolling and Simplifying Expressions with Template Haskell]<br />
:Ian Lynagh, May 2003.<br />
<br />
;[http://www.haskell.org/th/papers/hlpp.ps Automatic skeletons in Template Haskell]<br />
:Kevin Hammond, Jost Berthold and Rita Loogen, June 2003. Proceedings of 2003 Workshop on High Level Parallel Programming, Paris, France<br />
<br />
;[http://www.haskell.org/th/papers/Typing_Template_Haskell__Soft_Types.ps Typing Template Haskell: Soft Types]<br />
:Ian Lynagh, August 2004.<br />
<br />
==Dynamic typing==<br />
<br />
;[http://www.cs.uu.nl/groups/ST/stbib/swierstra-by-year/BaSw02.bib Typing dynamic typing]<br />
:A. I. Baars and S. D. Swierstra. In S. Peyton Jones, editor, Proceedings of the seventh ACM SIGPLAN international conference on Functional programming, pages 157--166. ACM Press, 2002<br />
<br />
==Parametricity==<br />
<br />
;[http://homepages.inf.ed.ac.uk/wadler/papers/free/free.ps.gz Theorems for free!]<br />
:Philip Wadler. 4'th International Conference on Functional Programming and Computer Architecture, London, September 1989.<br />
<br />
;[http://www.soi.city.ac.uk/~ross/papers/pointed.html Parametricity and Unboxing with Unpointed Types]<br />
:John Launchbury and Ross Paterson, European Symposium on Programming, LNCS, vol. 1058, pp. 204-218, Springer, Linkping, Sweden, 1996.<br />
<br />
;[http://wwwtcs.inf.tu-dresden.de/~voigt/seqFinal.pdf The Impact of seq on Free Theorems-Based Program Transformations]<br />
:Patricia Johann and Janis Voigtländer, Fundamenta Informaticae, vol. 69(1-2), pp. 63-102, 2006.<br />
<br />
;[http://wwwtcs.inf.tu-dresden.de/~voigt/TCS.pdf Selective strictness and parametricity in structural operational semantics, inequationally]<br />
:Janis Voigtländer and Patricia Johann, Theoretical Computer Science, vol. 388(1-3), pp. 290-318, 2007.<br />
<br />
;[http://wwwtcs.inf.tu-dresden.de/~voigt/pepm09-voigtlaender.pdf Proving Correctness via Free Theorems: The Case of the destroy/build-Rule]<br />
:Janis Voigtländer. Workshop on Partial Evaluation and Program Manipulation (PEPM'08), Proceedings, ACM Press, 2008.<br />
<br />
==Type classes==<br />
<br />
;[http://homepages.inf.ed.ac.uk/wadler/papers/class/class.ps.gz How to make ad-hoc polymorphism less ad hoc]<br />
:Philip Wadler and Stephen Blott. 16'th Symposium on Principles of Programming Languages, ACM Press, Austin, Texas, January 1989.<br />
<br />
;[http://research.microsoft.com/~simonpj/Papers/classhask.ps.gz Type classes in Haskell, CV Hall, K Hammond, SL Peyton Jones, and PL Wadler]<br />
:European Symposium On Programming, LNCS 788, Springer Verlag, pp. 241-256, April 1994. (Cited by 131)<br />
<br />
;[http://www.cse.ogi.edu/~mpj/pubs/pldi93.html Implementing Type Classes]<br />
:John Peterson and Mark P. Jones, In Proceedings of ACM SIGPLAN Symposium on Programming Language Design and Implementation, ACM SIGPLAN, June 1993. (Cited by 40)<br />
<br />
;[http://www.cs.chalmers.se/pub/cs-reports/papers/overload-fpca-93.ps.Z Implementing Haskell overloading]<br />
:Lennart Augustsson, 1993. FPCA. 65-73<br />
<br />
;[http://web.cecs.pdx.edu/~mpj/pubs/springschool.html Functional Programming with Overloading and Higher-Order Polymorphism]<br />
:Mark P. Jones, First International Spring School on Advanced Functional Programming Techniques, Baastad, Sweden, Springer-Verlag Lecture Notes in Computer Science 925, May 1995.<br />
<br />
;[http://research.microsoft.com/~simonpj/Papers/type-class-design-space Type classes: exploring the design space]<br />
:Simon Peyton Jones, Mark Jones, Erik Meijer, Haskell Workshop 1997.<br />
<br />
;[http://www.cse.ogi.edu/~mpj/pubs/fpca93.html A system of constructor classes: overloading and implicit higher-order polymorphism]<br />
:Mark P. Jones, In FPCA '93: Conference on Functional Programming Languages and Computer Architecture, Copenhagen, Denmark, June 1993.<br />
<br />
;[http://homepages.inf.ed.ac.uk/wadler/papers/overload2/overload2.ps.gz A second look at overloading]<br />
:Martin Odersky, Philip Wadler, Martin Wehr. 7'th International Conference on Functional Programming and Computer Architecture, ACM Press, San Diego, California, June 1995.<br />
<br />
;[http://citeseer.ist.psu.edu/laufer94combining.html Combining Type Classes and Existential Types]<br />
:Konstantin Laufer, Proceedings of the Latin American Informatic Conference (PANEL), 1994<br />
<br />
;[http://citeseer.ist.psu.edu/aufer95type.html Type Classes with Existential Types]<br />
:Konstantin Laufer, Journal of Functional Programming, 1996, May<br />
<br />
;[http://www.cse.unsw.edu.au/~chak/papers/DHCK06.html Modular Type Classes]<br />
:Derek Dreyer, Robert Harper, Manuel M.T. Chakravarty and Gabriele Keller, 2006<br />
<br />
;[http://www.informatik.uni-bonn.de/~ralf/hw2001/4.pdf Named instances for Haskell type classes]<br />
:W Kahl, J Scheffczyk - Proc. Haskell Workshop, 2001 (Cited by 12)<br />
<br />
===Deriving type classes===<br />
<br />
;[http://research.microsoft.com/~simonpj/Papers/derive.htm Derivable Type classes] <br />
:Ralf Hinze and Simon Peyton Jones, Haskell Workshop 2000.<br />
<br />
;[http://www.cis.upenn.edu/~sweirich/RepLib/ RepLib: A Library for Derivable Type Classes]<br />
:Stephanie Weirich 2006<br />
<br />
===Applications of type classes===<br />
<br />
;[http://okmij.org/ftp/Haskell/number-parameterized-types.html Number-parameterized types]<br />
:Oleg Kiselyov, The Monad.Reader. IssueFive. Oct 2nd, 2005<br />
<br />
;[http://web.comlab.ox.ac.uk/oucl/work/jeremy.gibbons/publications/typecase.pdf TypeCase: a design pattern for type-indexed functions]<br />
:Bruno C. d. S. Oliveira, Jeremy Gibbons. Proceedings of the 2005 ACM SIGPLAN workshop on Haskell. Tallinn, Estonia. 98 - 109, 2005 ISBN:1-59593-071-X<br />
<br />
;[http://okmij.org/ftp/Haskell/types.html#Prepose Functional pearl: implicit configurations--or, type classes reflect the values of types]<br />
:Oleg Kiselyov, Chung-chieh Shan, Proceedings of the 2004 ACM SIGPLAN workshop on Haskell, Snowbird, Utah, USA, 2004 ISBN 1-58113-850-4<br />
<br />
;[http://www.comp.nus.edu.sg/~sulzmann/publications/extract-typeclassproofs.pdf Extracting Programs from Type Class Proofs]<br />
:Martin Sulzmann, 2006<br />
<br />
;[http://www.comp.nus.edu.sg/~sulzmann/manuscript/coind-type-class-proofs.ps Co-induction and Type Improvement in Type Class Proofs]<br />
:Martin Sulzmann, Jeremy Wazny and Peter J. Stuckey. 2005<br />
<br />
;[http://www.cs.nott.ac.uk/~ctm/faking.ps.gz Faking It (Simulating Dependent Types in Haskell)]<br />
:Conor McBride, Journal of Functional Programming, 12(4&5):375-392, July 2002<br />
<br />
;[http://www.comp.nus.edu.sg/~sulzmann/manuscript/aophaskell.ps.gz Aspect-Oriented Programming with Type Classes]<br />
:Martin Sulzmann and Meng Wang, 2006.<br />
<br />
;[http://wwwtcs.inf.tu-dresden.de/~voigt/mpc08.pdf Asymptotic Improvement of Computations over Free Monads]<br />
:Janis Voigtländer. Mathematics of Program Construction (MPC'08), Proceedings, LNCS 5133:388-403, Springer-Verlag, 2008.<br />
<br />
<br />
==Undecidable instances==<br />
<br />
;[http://www.haskell.org/ghc/docs/6.4.2/html/users_guide/type-extensions.html#undecidable-instances Undecidable instances]<br />
:GHC User's Guide.<br />
<br />
==Multi-parameter type classes==<br />
<br />
;[http://www.comp.nus.edu.sg/~sulzmann/publications/ghc-mptc-inf.ps Principal Type Inference for GHC-Style Multi-Parameter Type Classes]<br />
:Martin Sulzmann, Tom Schrijvers and Peter J. Stuckey. In APLAS'06.<br />
<br />
;[http://www.comp.nus.edu.sg/~sulzmann/manuscript/mptc-inf-old.pdf Type Inference for Multi-Parameter Type Classes]<br />
:Martin Sulzmann and Peter J. Stuckey. 2005<br />
<br />
;[http://ostrich.lcs.mit.edu/cgi-bin/pickbib?jfp::DugganO2002 Type-checking multi-parameter type classes]<br />
:Dominic Duggan and John Ophel, Journal of Functional Programming, 12(2):133-158, March 2002<br />
<br />
==Functional dependencies==<br />
<br />
;[http://www.cse.ogi.edu/~mpj/pubs/fundeps.html Type Classes with Functional Dependencies]<br />
:Mark P. Jones, In Proceedings of the 9th European Symposium on Programming, ESOP 2000, Berlin, Germany, March 2000, Springer-Verlag LNCS 1782.<br />
<br />
;[http://research.microsoft.com/~simonpj/Papers/fd-chr/index.htm Sound and Decidable Type Inference for Functional Dependencies]<br />
:Gregory J. Duck, Simon Peyton Jones, Peter J. Stuckey, and Martin Sulzmann, European Symposium on Programming 2004 (ESOP'04).<br />
<br />
;[http://www.comp.nus.edu.sg/~sulzmann/publications/jfp-fds-revised.pdf Understanding Functional Dependencies via Constraint Handling Rules]<br />
:Martin Sulzmann, Gregory J. Duck, Simon Peyton-Jones and Peter J. Stuckey.j To appear in Journal of Functional Programming. 2006<br />
<br />
;[http://www.comp.nus.edu.sg/~sulzmann/manuscript/afds.ps Associated Functional Dependencies]<br />
:Martin Sulzmann and Edmund Soon Lee Lam. 2005<br />
<br />
==Constraint Handling Rules==<br />
<br />
;[http://www.comp.nus.edu.sg/~sulzmann/publications/aplas06-invited.pdf Type Processing by Constraint Reasoning]<br />
:Peter J. Stuckey, Martin Sulzmann and Jeremy Wazny, In APLAS'06.<br />
<br />
;[http://www.comp.nus.edu.sg/~sulzmann/manuscript/chr-stm.ps A Concurrent Constraint Handling Rules Implementation in Haskell with Software Transactional Memory]<br />
:Edmund S.L. Lam and Martin Sulzmann<br />
<br />
;[http://www.comp.nus.edu.sg/~sulzmann/publications/chr06-observable.ps Observable Confluence for Constraint Handling Rules]<br />
:Gregory J. Duck, Peter J. Stuckey and Martin Sulzmann<br />
<br />
==Generalised Algebraic Data Types (GADTs)==<br />
<br />
;[http://research.microsoft.com/~simonpj/papers/gadt/index.htm Simple unification-based type inference for GADTs]<br />
:Simon Peyton Jones, Dimitrios Vytiniotis, Stephanie Weirich, and Geoffrey Washburn. Submitted to PLDI 2005<br />
<br />
;[http://www.cis.upenn.edu/~geoffw/research/papers/MS-CIS-05-26.pdf Wobbly types: type inference for generalised algebraic data types]<br />
:S Peyton Jones, G. Washburn, and S. Weirich. 2004.<br />
<br />
;[http://www.comp.nus.edu.sg/~sulzmann/manuscript/simple-translate-gadts.ps Translating Generalized Algebraic Data Types to System F]<br />
:Martin Sulzmann and Meng Wang. 2005<br />
<br />
;[http://cristal.inria.fr/~fpottier/publis/pottier-regis-gianas-05.pdf Stratified type inference for generalized algebraic data types]<br />
:François Pottier and Yann Régis-Gianas, 2006<br />
<br />
;[http://www.comp.nus.edu.sg/~sulzmann/manuscript/gadt-short.ps Type Inference for GADTs via Herbrand Constraint Abduction]<br />
:Martin Sulzmann, Tom Schrijvers and Peter J. Stuckey, 2006 <br />
<br />
;[http://www.comp.nus.edu.sg/~sulzmann/publications/tr-eadt.ps.gz A Framework for Extended Algebraic Data Types]<br />
:Martin Sulzmann, Jeremy Wazny and Peter J. Stuckey, 2006<br />
<br />
See also the [[GADT]] page.<br />
<br />
==Parametric Regular Data Types==<br />
<br />
;[http://www.comp.nus.edu.sg/~sulzmann/manuscript/parametric-regular.ps Type Inference and Compilation for Parametric Regular Data Types]<br />
:Martin Sulzmann and Kenny Zhuo Ming Lu, 2006<br />
<br />
;[http://www.comp.nus.edu.sg/~sulzmann/manuscript/haskell-xduce.ps The Marriage of Haskell and XDuce]<br />
:Martin Sulzmann and Kenny Zhuo Ming Lu<br />
<br />
==Type Families and Associated types==<br />
<br />
;[http://www.haskell.org/~simonmar/papers/assoc.pdf Associated types with class]<br />
:Manuel M. T. Chakravarty, Gabriele Keller, Simon Peyton Jones, Simon Marlow) POPL '05: Proceedings of the 32nd ACM SIGPLAN-SIGACT sysposium on Principles of programming languages, pages 1--13, Long Beach, California, USA, ACM Press, 2005<br />
<br />
;[http://www.cse.unsw.edu.au/~chak/papers/CKP05.html Associated Type Synonyms]<br />
:Manuel M. T. Chakravarty, Gabriele Keller, and Simon Peyton Jones. In Proceedings of The Tenth ACM SIGPLAN International Conference on Functional Programming, ACM Press, pages 241-253, 2005.<br />
<br />
;[http://www.informatik.uni-freiburg.de/~wehr/diplom ML Modules and Haskell Type Classes: A Constructive Comparison]<br />
:Stefan Wehr Diplomarbeit. Albert-Ludwigs-Universitt Freiburg, Fakultt fr Angewandte Wissenschaften, Institut fr Informatik, November 2005. <br />
<br />
;[http://www.cse.unsw.edu.au/~chak/papers/SCP06.html System F with Type Equality Coercions]<br />
:Martin Sulzmann, Manuel M. T. Chakravarty, and Simon Peyton Jones.<br />
<br />
;[http://www.cs.kuleuven.be/~toms/Research/papers/type_functions.pdf Towards Open Type Functions for Haskell]<br />
:Tom Schrijvers, Simon Peyton Jones, Martin Sulzmann, and Manuel Chakravarty. In Proceedings of IFL' 07, Freiburg, Germany, 2007.<br />
<br />
;[http://www.cs.kuleuven.be/~toms/Research/papers/draft_type_functions_2008.pdf Type Checking with Open Type Functions for Haskell]<br />
:Tom Schrijvers, Simon Peyton Jones, Manuel Chakravarty, and Martin Sulzmann. In Proceedings of ICFP' 08, Victoria, Canada, 2008.<br />
<br />
<br />
==Arbitrary-rank polymorphism==<br />
<br />
;[http://www.ubka.uni-karlsruhe.de/vvv/1996/informatik/81/81.pdf.gz Putting type annotations to work]<br />
:Martin Odersky and Konstantin Läufer. Proceedings of the 23rd ACM SIGPLAN-SIGACT symposium on Principles of programming languages. St. Petersburg Beach, Florida, United States. 54 - 67 1996 ISBN 0-89791-769-3<br />
<br />
;[http://journals.cambridge.org/production/action/cjoGetFulltext%3Ffulltextid%3D445910 Practical type inference for arbitrary-rank types]<br />
:SP Jones, M Shields - Submitted to the Journal of Functional Programming, 2005<br />
<br />
==Phantom types==<br />
<br />
;[http://techreports.library.cornell.edu:8081/Dienst/UI/1.0/Display/cul.cis/TR2003-1901 First-class phantom types]<br />
:James Cheney and Ralf Hinze. Technical Report TR2003-1901, Cornell University, 2003.<br />
<br />
;[http://ttic.uchicago.edu/~fluet/research/phantom-subtyping/jfp06/jfp06.pdf Phantom Types and Subtyping]<br />
:Matthew Fluet and Riccardo Pucella. Submitted to the Journal of Functional Programming, 2006.<br />
<br />
==Implicit parameters==<br />
<br />
;[http://www.cse.ogi.edu/~mbs/pub/implicit_parameters/implicit.ps Implicit Parameters: Dynamic Scoping with Static Types]<br />
:Jeffrey Lewis, Mark Shields, Erik Meijer and John Launchbury. POPL'00. 2000.<br />
<br />
;[http://www.cs.chalmers.se/~rjmh/Globals.ps Global variables in Haskell]<br />
:John Hughes. J. Funct. Program. 14(5): 489-502 (2004) <br />
<br />
;[http://www.cs.uu.nl/pub/RUU/CS/techreps/CS-2004/2004-059.pdf Explicit Implicit Parameters]<br />
:A. Dijkstra and S. D. Swierstra. UU-CS 2004-059, 2004.<br />
<br />
==Object oriented Haskell==<br />
<br />
;[http://research.microsoft.com/~simonpj/Papers/oo-haskell/index.htm Object-Oriented Style Overloading for Haskell] <br />
:Mark Shields and Simon Peyton Jones; BABEL workshop '01.<br />
<br />
;[http://www.cse.unsw.edu.au/~chak/papers/PC03.html Interfacing Haskell with Object-Oriented Languages]<br />
:Andr T. H. Pang and Manuel M. T. Chakravarty. In Greg Michaelson and Phil Trinder, editors, Implementation of Functional Languages: 15th International Workshop, IFL 2003, Edinburgh, UK, September 8-11, 2003, Revised Papers, LNCS 3145, Springer-Verlag, pages 20-36, 2004. <br />
<br />
;[http://citeseer.ist.psu.edu/118134.html Haskell++: An Object-Oriented Extension of Haskell]<br />
:Jan Sparud and John Hughes. Haskell Workshop 1995<br />
<br />
;[http://homepages.cwi.nl/~ralf/OOHaskell/ Haskell's overlooked object system]<br />
:Oleg Kiselyov and Ralf Lämmel, submitted for journal publication; online since 30 Sep. 2004;<br />
<br />
==Restricted Datatypes==<br />
<br />
;[http://www.cs.chalmers.se/~rjmh/Papers/restricted-datatypes.ps Restricted datatypes]<br />
:John Hughes. 1999 Haskell workshop<br />
<br />
==Patterns==<br />
<br />
;[http://www.cs.yale.edu/homes/tullsen/patterns.ps First Class Patterns]<br />
:Mark Tullsen. Practical Aspects of Declarative Languages, Second International Workshop, PADL 2000. volume 1753 of Lecture Notes in Computer Science. January 2000. <br />
<br />
===Pattern guards===<br />
<br />
;[http://research.microsoft.com/~simonpj/Papers/pat.htm Pattern Guards and Transformational Patterns]<br />
:Martin Erwig and Simon Peyton Jones; Haskell Workshop 2000.<br />
<br />
;[http://research.microsoft.com/Users/simonpj/Haskell/guards.html A new view of guards]<br />
:Simon Peyton Jones, April 1997<br />
<br />
===Views===<br />
<br />
;[http://www.haskell.org/development/views.html Views: An Extension to Haskell Pattern Matching]<br />
:Warren Burton, Erik Meijer, Patrick Sansom, Simon Thompson and Phil Wadler.<br />
<br />
;[http://homepages.inf.ed.ac.uk/wadler/papers/view/view.ps.gz Views: A way for pattern matching to cohabit with data abstraction]<br />
:POPL 14 (1987), 307-313.<br />
<br />
==Qualified types==<br />
<br />
;[http://haskell.readscheme.org/servlets/cite.ss?pattern=mpj-jones1994a Qualified Types: Theory and Practice]<br />
:Mark P. Jones. PhD. Thesis. Yale University. November 1994.<br />
<br />
;[http://www.cse.ogi.edu/~mpj/pubs/fpca95.ps Simplifying and Improving Qualified Types]<br />
:Mark P. Jones. FPCA '95: Conference on Functional Programming Languages and Computer Architecture. June 1995.<br />
<br />
;[http://www.cse.ogi.edu/~mpj/pubs/RR-1040.ps Simplifying and Improving Qualified Types]<br />
:Mark P. Jones. Yale University. Research Report YALEU/DCS/RR-1040. June 1994.<br />
<br />
;[http://www.cse.ogi.edu/~mpj/pubs/RR-989.ps Coherence for qualified types]<br />
:Mark P. Jones. Yale University. Research Report YALEU/DCS/RR-989. September 1993. <br />
<br />
;[http://www.cse.ogi.edu/~mpj/pubs/rev-qual-types.ps A theory of qualified types]<br />
:Mark P. Jones. ESOP '92: European Symposium on Programming. Lecture Notes in Computer Science, 582. February 1992. (Cited by 68)<br />
<br />
==Polymorphic recursion==<br />
<br />
;[http://portal.acm.org/citation.cfm%3Fcoll%3DGUIDE%26dl%3DGUIDE%26id%3D169692 Type inference with polymorphic recursion]<br />
:F Henglein - ACM Transactions on Programming Languages and Systems (1993)<br />
<br />
;[http://www.jucs.org/jucs_9_8/practical_type_inference_for/paper.pdf Practical Type Inference for Polymorphic Recursion: an Implementation in Haskell]<br />
:C Vasconcellos, L Figueiredo, C Camarao - Journal of Universal Computer Science, 2003<br />
<br />
;[http://www.dcc.ufmg.br/~camarao/ml0-impl.ps Type Inference for Polymorphic Recursive Definitions: a Specification in Haskell]<br />
:L Figueiredo, C Camarao<br />
<br />
[[Category:Research]]<br />
[[Category:Type-level programming]]</div>Tschrijvershttps://wiki.haskell.org/index.php?title=Research_papers/Type_systems&diff=16861Research papers/Type systems2007-11-15T02:33:51Z<p>Tschrijvers: </p>
<hr />
<div>__TOC__<br />
<br />
==Haskell semantics==<br />
<br />
;[http://research.microsoft.com/~simonpj/Papers/static-semantics.dvi.gz A static semantics for Haskell]<br />
:SL Peyton Jones and PL Wadler, (draft), Department of Computing Science, University of Glasgow, 1992. (Cited by 20)<br />
<br />
;[http://haskell.org/onlinereport/dynamic-semantics.dvi.gz A Dynamic Semantics for Haskell] <br />
:Kevin Hammond and Cordelia Hall, (draft), University of Glasgow, 1992, 23 pages.<br />
<br />
;[http://www.cse.ogi.edu/~mpj/pubs/thih.html Typing Haskell in Haskell] <br />
:Mark P. Jones, In Proceedings of the 1999 Haskell Workshop, Paris, France, October 1999. Published in Technical Report UU-CS-1999-28, Department of Computer Science, University of Utrecht. (Cited by 66)<br />
<br />
;[http://www.pms.informatik.uni-muenchen.de/mitarbeiter/panne/haskell_libs/hsparser.html HParser]<br />
:A parser for Haskell written purely in Haskell (using the Happy parser generator).<br />
<br />
;[http://www.cse.ogi.edu/~hallgren/Talks/LHiH/ A Lexer for Haskell in Haskell]<br />
:Thomas Hallgren, PacSoft Oregon Graduate Institute, 14 January, 2002<br />
<br />
;[http://citeseer.ist.psu.edu/launchbury93natural.html A Natural Semantics for Lazy Evaluation]<br />
:John Launchbury, Conference Record of the Twentieth Annual ACM SIGPLAN-SIGACT Symposium on Principles of Programming Languages, Charleston, South Carolina, 144--154, 1993.<br />
<br />
;[http://www.cs.nott.ac.uk/~gmh/papers/11.ps A Space Semantics for Core Haskell]<br />
:Adam Bakewell. Proc. 2000 Haskell Workshop. September 2001.<br />
<br />
==Pure type systems==<br />
<br />
;[http://research.microsoft.com/~simonpj/Papers/henk.ps.gz Henk: a typed intermediate language]<br />
:SL Peyton Jones and E Meijer, Proceedings of the Types in Compilation Workshop, Amsterdam, June 1997.<br />
<br />
;[http://www.cs.uu.nl/~johanj/MSc/jwroorda/ Pure Type Systems for Functional Programming]<br />
:Jan-Willem Roorda, Masters Thesis, University of Utrecht, INF/SCR-00-13, available online, 2000<br />
<br />
==Dependent Types==<br />
<br />
;[http://www.cs.nott.ac.uk/~txa/publ/ydtm.pdf Why Dependent Types Matter]<br />
:Thorsten Altenkirch and Conor McBride and James McKinna, Manuscript, available online, April, 2005. (Cited by 7)<br />
<br />
;[http://www.informatik.uni-bonn.de/~loeh/LambdaPi.html Simply Easy! An Implementation of a Dependently Typed Lambda Calculus]<br />
:Andres Löh, Conor McBride and Wouter Swierstra, 2007.<br />
<br />
==Unboxed values==<br />
<br />
;[http://www.soi.city.ac.uk/~ross/papers/pointed.html Parametricity and Unboxing with Unpointed Types]<br />
:John Launchbury and Ross Paterson, European Symposium on Programming, LNCS, vol. 1058, pp. 204-218, Springer, Linkping, Sweden, 1996.<br />
<br />
;[http://research.microsoft.com/~simonpj/Papers/unboxed-values.ps.Z Unboxed values as first class citizens]<br />
:SL Peyton Jones and J Launchbury, Functional Programming Languages and Computer Architecture (FPCA'91), Boston, LNCS 523, Springer Verlag, Sept 1991, pp636-666. (Cited by 105)<br />
<br />
==Modules==<br />
<br />
;[http://www.cse.ogi.edu/~diatchki/papers/modules98.pdf A Formal Specification of the Haskell 98 Module System]<br />
:Iavor S. Diatchki, Mark P. Jones, and Thomas Hallgren. Proceedings of the 2002 ACM SIGPLAN workshop on Haskell. Pittsburgh, Pennsylvania. 17 - 28 2002 ISBN 1-58113-605-6 (Cited by 12)<br />
<br />
;[http://research.microsoft.com/~simonpj/Papers/first-class-modules/index.htm First class modules for Haskell]<br />
:Mark Shields and Simon Peyton Jones; FOOL'02.<br />
<br />
;[http://research.microsoft.com/~simonpj/Papers/Nicklisch-modules.ps.gz An exploration of modular programs]<br />
:Electronic proceedings of the 1996 Glasgow Functional Programming Workshop, J Nicklisch and SL Peyton Jones, Ullapool, July 1996.<br />
<br />
==Exceptions==<br />
<br />
;[http://www.haskell.org/~simonmar/papers/ext-exceptions.pdf An Extensible Dynamically-Typed Hierarchy of Exceptions]<br />
:Simon Marlow. Haskell '06: Proceedings of the 2006 ACM SIGPLAN workshop on Haskell, Portland, Oregon, ACM Press, September 2006<br />
<br />
;[http://research.microsoft.com/~simonpj/Papers/imprecise-exn-sem.htm Imprecise Exceptions, Co-Inductively]<br />
:Andy Moran, Soeren Lassen, and Simon Peyton Jones. HOOTS'99.<br />
<br />
;[http://research.microsoft.com/~simonpj/Papers/imprecise-exn.htm A semantics for imprecise exceptions]<br />
:Simon Peyton Jones, Alastair Reid, Tony Hoare, Simon Marlow, Fergus Henderson. Proc Programming Language Design and Implementation (PLDI'99), Atlanta.<br />
<br />
;[http://research.microsoft.com/~simonpj/Papers/asynch-exns.htm Asynchronous exceptions in Haskell]<br />
:Simon Marlow, Simon Peyton Jones, Andy Moran and John Reppy, PLDI'01.<br />
<br />
;[http://www.reid-consulting-uk.ltd.uk/alastair/publications/except6.ps.gz Handling Exceptions in Haskell]<br />
:A. Reid, Research Report YALEU/DCS/RR-1175, Yale University, August, 1998<br />
<br />
==Lexically scoped type variables==<br />
<br />
;[http://research.microsoft.com/%7Esimonpj/papers/scoped%2Dtyvars/ Lexically scoped type variables]<br />
:Simon Peyton Jones and Mark Shields. 2004.<br />
<br />
==Records==<br />
<br />
;[http://research.microsoft.com/~simonpj/Papers/records.htm Lightweight Extensible Records for Haskell]<br />
:Mark Jones and Simon Peyton Jones, Haskell Workshop 1999.<br />
<br />
;[http://www.cs.uu.nl/~daan/download/papers/scopedlabels.pdf Extensible records with scoped labels]<br />
:Daan Leijen. The 2005 Symposium on Trends in Functional Programming (TFP'05), Tallin, Estonia, September 2005.<br />
<br />
;[http://www.cs.uu.nl/~daan/download/papers/fclabels.pdf First-class labels for extensible rows]<br />
:Daan Leijen. Technical Report UU-CS-2004-51, Departement of Computer Science, Universiteit Utrecht, 2004.<br />
<br />
;[http://www.reid-consulting-uk.ltd.uk/alastair/publications/h-wkshop95a/index.html Haskell Records]<br />
:J. Peterson, A. Reid, Proceedings of the Haskell Workshop, La Jolla, June 1995. <br />
<br />
;[http://www.cse.ogi.edu/~mpj/pubs/96-3.ps.gz A Polymorphic Type System for Extensible Records and Variants]<br />
:Benedict R. Gaster and Mark P. Jones. Department of Computer Science, University of Nottingham. Technical report NOTTCS-TR-96-3. November 1996.<br />
<br />
==Meta programming==<br />
<br />
;[http://research.microsoft.com/copyright/accept.asp?path=/users/simonpj/papers/dyntyping.ps.gz&pub=ACM Dynamic typing as staged type inference]<br />
:MB Shields, T Sheard, and SL Peyton Jones, POPL98.<br />
<br />
;[http://research.microsoft.com/~simonpj/Papers/meta-haskell/index.htm Template meta-programming for Haskell]<br />
:Tim Sheard and Simon Peyton Jones, Proceedings of the Haskell Workshop, Pittsburgh, 2002<br />
<br />
;[http://www.cse.unsw.edu.au/~chak/papers/SCK04.html Optimising Embedded DSLs using Template Haskell]<br />
:Sean Seefried, Manuel M. T. Chakravarty, and Gabriele Keller. In Gabor Karsai and Eelco Visser, editors, Third International Conference on Generative Programming and Component Engineering (GPCE'04), LNCS 3286, Springer-Verlag, pages 186-205, 2004. [An earlier draft was presented at the IFL 2003 - 15th International Workshop on the Implementation of Functional Languages, 2003.<br />
<br />
;[http://www.haskell.org/th/papers/Unrolling_and_Simplifying_Expressions_with_Template_Haskell.ps Unrolling and Simplifying Expressions with Template Haskell]<br />
:Ian Lynagh, May 2003.<br />
<br />
;[http://www.haskell.org/th/papers/hlpp.ps Automatic skeletons in Template Haskell]<br />
:Kevin Hammond, Jost Berthold and Rita Loogen, June 2003. Proceedings of 2003 Workshop on High Level Parallel Programming, Paris, France<br />
<br />
;[http://www.haskell.org/th/papers/Typing_Template_Haskell__Soft_Types.ps Typing Template Haskell: Soft Types]<br />
:Ian Lynagh, August 2004.<br />
<br />
==Dynamic typing==<br />
<br />
;[http://www.cs.uu.nl/groups/ST/stbib/swierstra-by-year/BaSw02.bib Typing dynamic typing]<br />
:A. I. Baars and S. D. Swierstra. In S. Peyton Jones, editor, Proceedings of the seventh ACM SIGPLAN international conference on Functional programming, pages 157--166. ACM Press, 2002<br />
<br />
==Parametricity==<br />
<br />
;[http://homepages.inf.ed.ac.uk/wadler/papers/free/free.ps.gz Theorems for free!]<br />
:Philip Wadler. 4'th International Conference on Functional Programming and Computer Architecture, London, September 1989.<br />
<br />
;[http://www.soi.city.ac.uk/~ross/papers/pointed.html Parametricity and Unboxing with Unpointed Types]<br />
:John Launchbury and Ross Paterson, European Symposium on Programming, LNCS, vol. 1058, pp. 204-218, Springer, Linkping, Sweden, 1996.<br />
<br />
;[http://wwwtcs.inf.tu-dresden.de/~voigt/seqFinal.pdf The Impact of seq on Free Theorems-Based Program Transformations]<br />
:Patricia Johann and Janis Voigtländer, Fundamenta Informaticae, vol. 69(1-2), pp. 63-102, 2006.<br />
<br />
==Type classes==<br />
<br />
;[http://homepages.inf.ed.ac.uk/wadler/papers/class/class.ps.gz How to make ad-hoc polymorphism less ad hoc]<br />
:Philip Wadler and Stephen Blott. 16'th Symposium on Principles of Programming Languages, ACM Press, Austin, Texas, January 1989.<br />
<br />
;[http://research.microsoft.com/~simonpj/Papers/classhask.ps.gz Type classes in Haskell, CV Hall, K Hammond, SL Peyton Jones, and PL Wadler]<br />
:European Symposium On Programming, LNCS 788, Springer Verlag, pp. 241-256, April 1994. (Cited by 131)<br />
<br />
;[http://www.cse.ogi.edu/~mpj/pubs/pldi93.html Implementing Type Classes]<br />
:John Peterson and Mark P. Jones, In Proceedings of ACM SIGPLAN Symposium on Programming Language Design and Implementation, ACM SIGPLAN, June 1993. (Cited by 40)<br />
<br />
;[http://www.cs.chalmers.se/pub/cs-reports/papers/overload-fpca-93.ps.Z Implementing Haskell overloading]<br />
:Lennart Augustsson, 1993. FPCA. 65-73<br />
<br />
;[http://web.cecs.pdx.edu/~mpj/pubs/springschool.html Functional Programming with Overloading and Higher-Order Polymorphism]<br />
:Mark P. Jones, First International Spring School on Advanced Functional Programming Techniques, Baastad, Sweden, Springer-Verlag Lecture Notes in Computer Science 925, May 1995.<br />
<br />
;[http://research.microsoft.com/~simonpj/Papers/type-class-design-space Type classes: exploring the design space]<br />
:Simon Peyton Jones, Mark Jones, Erik Meijer, Haskell Workshop 1997.<br />
<br />
;[http://www.cse.ogi.edu/~mpj/pubs/fpca93.html A system of constructor classes: overloading and implicit higher-order polymorphism]<br />
:Mark P. Jones, In FPCA '93: Conference on Functional Programming Languages and Computer Architecture, Copenhagen, Denmark, June 1993.<br />
<br />
;[http://homepages.inf.ed.ac.uk/wadler/papers/overload2/overload2.ps.gz A second look at overloading]<br />
:Martin Odersky, Philip Wadler, Martin Wehr. 7'th International Conference on Functional Programming and Computer Architecture, ACM Press, San Diego, California, June 1995.<br />
<br />
;[http://citeseer.ist.psu.edu/laufer94combining.html Combining Type Classes and Existential Types]<br />
:Konstantin Laufer, Proceedings of the Latin American Informatic Conference (PANEL), 1994<br />
<br />
;[http://citeseer.ifi.unizh.ch/laeufer95type.html Type Classes with Existential Types]<br />
:Konstantin Laufer, Journal of Functional Programming, 1996, May<br />
<br />
;[http://www.cse.unsw.edu.au/~chak/papers/DHCK06.html Modular Type Classes]<br />
:Derek Dreyer, Robert Harper, Manuel M.T. Chakravarty and Gabriele Keller, 2006<br />
<br />
;[http://www.informatik.uni-bonn.de/~ralf/hw2001/4.pdf Named instances for Haskell type classes]<br />
:W Kahl, J Scheffczyk - Proc. Haskell Workshop, 2001 (Cited by 12)<br />
<br />
===Deriving type classes===<br />
<br />
;[http://research.microsoft.com/~simonpj/Papers/derive.htm Derivable Type classes] <br />
:Ralf Hinze and Simon Peyton Jones, Haskell Workshop 2000.<br />
<br />
;[http://www.cis.upenn.edu/~sweirich/RepLib/ RepLib: A Library for Derivable Type Classes]<br />
:Stephanie Weirich 2006<br />
<br />
===Applications of type classes===<br />
<br />
;[http://okmij.org/ftp/Haskell/number-parameterized-types.html Number-parameterized types]<br />
:Oleg Kiselyov, The Monad.Reader. IssueFive. Oct 2nd, 2005<br />
<br />
;[http://web.comlab.ox.ac.uk/oucl/work/jeremy.gibbons/publications/typecase.pdf TypeCase: a design pattern for type-indexed functions]<br />
:Bruno C. d. S. Oliveira, Jeremy Gibbons. Proceedings of the 2005 ACM SIGPLAN workshop on Haskell. Tallinn, Estonia. 98 - 109, 2005 ISBN:1-59593-071-X<br />
<br />
;[http://okmij.org/ftp/Haskell/types.html#Prepose Functional pearl: implicit configurations--or, type classes reflect the values of types]<br />
:Oleg Kiselyov, Chung-chieh Shan, Proceedings of the 2004 ACM SIGPLAN workshop on Haskell, Snowbird, Utah, USA, 2004 ISBN 1-58113-850-4<br />
<br />
;[http://www.comp.nus.edu.sg/~sulzmann/publications/extract-typeclassproofs.pdf Extracting Programs from Type Class Proofs]<br />
:Martin Sulzmann, 2006<br />
<br />
;[http://www.comp.nus.edu.sg/~sulzmann/manuscript/coind-type-class-proofs.ps Co-induction and Type Improvement in Type Class Proofs]<br />
:Martin Sulzmann, Jeremy Wazny and Peter J. Stuckey. 2005<br />
<br />
;[http://www.cs.nott.ac.uk/~ctm/faking.ps.gz Faking It (Simulating Dependent Types in Haskell)]<br />
:Conor McBride, Journal of Functional Programming, 12(4&5):375-392, July 2002<br />
<br />
;[http://www.comp.nus.edu.sg/~sulzmann/manuscript/aophaskell.ps.gz Aspect-Oriented Programming with Type Classes]<br />
:Martin Sulzmann and Meng Wang, 2006.<br />
<br />
==Undecidable instances==<br />
<br />
;[http://www.haskell.org/ghc/docs/6.4.2/html/users_guide/type-extensions.html#undecidable-instances Undecidable instances]<br />
:GHC User's Guide.<br />
<br />
==Multi-parameter type classes==<br />
<br />
;[http://www.comp.nus.edu.sg/~sulzmann/publications/ghc-mptc-inf.ps Principal Type Inference for GHC-Style Multi-Parameter Type Classes]<br />
:Martin Sulzmann, Tom Schrijvers and Peter J. Stuckey. In APLAS'06.<br />
<br />
;[http://www.comp.nus.edu.sg/~sulzmann/manuscript/mptc-inf-old.pdf Type Inference for Multi-Parameter Type Classes]<br />
:Martin Sulzmann and Peter J. Stuckey. 2005<br />
<br />
;[http://ostrich.lcs.mit.edu/cgi-bin/pickbib?jfp::DugganO2002 Type-checking multi-parameter type classes]<br />
:Dominic Duggan and John Ophel, Journal of Functional Programming, 12(2):133-158, March 2002<br />
<br />
==Functional dependencies==<br />
<br />
;[http://www.cse.ogi.edu/~mpj/pubs/fundeps.html Type Classes with Functional Dependencies]<br />
:Mark P. Jones, In Proceedings of the 9th European Symposium on Programming, ESOP 2000, Berlin, Germany, March 2000, Springer-Verlag LNCS 1782.<br />
<br />
;[http://research.microsoft.com/~simonpj/Papers/fd-chr/index.htm Sound and Decidable Type Inference for Functional Dependencies]<br />
:Gregory J. Duck, Simon Peyton Jones, Peter J. Stuckey, and Martin Sulzmann, European Symposium on Programming 2004 (ESOP'04).<br />
<br />
;[http://www.comp.nus.edu.sg/~sulzmann/publications/jfp-fds-revised.pdf Understanding Functional Dependencies via Constraint Handling Rules]<br />
:Martin Sulzmann, Gregory J. Duck, Simon Peyton-Jones and Peter J. Stuckey.j To appear in Journal of Functional Programming. 2006<br />
<br />
;[http://www.comp.nus.edu.sg/~sulzmann/manuscript/afds.ps Associated Functional Dependencies]<br />
:Martin Sulzmann and Edmund Soon Lee Lam. 2005<br />
<br />
==Constraint Handling Rules==<br />
<br />
;[http://www.comp.nus.edu.sg/~sulzmann/publications/aplas06-invited.pdf Type Processing by Constraint Reasoning]<br />
:Peter J. Stuckey, Martin Sulzmann and Jeremy Wazny, In APLAS'06.<br />
<br />
;[http://www.comp.nus.edu.sg/~sulzmann/manuscript/chr-stm.ps A Concurrent Constraint Handling Rules Implementation in Haskell with Software Transactional Memory]<br />
:Edmund S.L. Lam and Martin Sulzmann<br />
<br />
;[http://www.comp.nus.edu.sg/~sulzmann/publications/chr06-observable.ps Observable Confluence for Constraint Handling Rules]<br />
:Gregory J. Duck, Peter J. Stuckey and Martin Sulzmann<br />
<br />
==Generalised Algebraic Data Types (GADTs)==<br />
<br />
;[http://research.microsoft.com/~simonpj/papers/gadt/index.htm Simple unification-based type inference for GADTs]<br />
:Simon Peyton Jones, Dimitrios Vytiniotis, Stephanie Weirich, and Geoffrey Washburn. Submitted to PLDI 2005<br />
<br />
;[http://www.cis.upenn.edu/~geoffw/research/papers/MS-CIS-05-26.pdf Wobbly types: type inference for generalised algebraic data types]<br />
:S Peyton Jones, G. Washburn, and S. Weirich. 2004.<br />
<br />
;[http://www.comp.nus.edu.sg/~sulzmann/manuscript/simple-translate-gadts.ps Translating Generalized Algebraic Data Types to System F]<br />
:Martin Sulzmann and Meng Wang. 2005<br />
<br />
;[http://cristal.inria.fr/~fpottier/publis/pottier-regis-gianas-05.pdf Stratified type inference for generalized algebraic data types]<br />
:François Pottier and Yann Régis-Gianas, 2006<br />
<br />
;[http://www.comp.nus.edu.sg/~sulzmann/manuscript/gadt-short.ps Type Inference for GADTs via Herbrand Constraint Abduction]<br />
:Martin Sulzmann, Tom Schrijvers and Peter J. Stuckey, 2006 <br />
<br />
;[http://www.comp.nus.edu.sg/~sulzmann/publications/tr-eadt.ps.gz A Framework for Extended Algebraic Data Types]<br />
:Martin Sulzmann, Jeremy Wazny and Peter J. Stuckey, 2006<br />
<br />
See also the [[GADT]] page.<br />
<br />
==Parametric Regular Data Types==<br />
<br />
;[http://www.comp.nus.edu.sg/~sulzmann/manuscript/parametric-regular.ps Type Inference and Compilation for Parametric Regular Data Types]<br />
:Martin Sulzmann and Kenny Zhuo Ming Lu, 2006<br />
<br />
;[http://www.comp.nus.edu.sg/~sulzmann/manuscript/haskell-xduce.ps The Marriage of Haskell and XDuce]<br />
:Martin Sulzmann and Kenny Zhuo Ming Lu<br />
<br />
==Associated types==<br />
<br />
;[http://www.haskell.org/~simonmar/papers/assoc.pdf Associated types with class]<br />
:Manuel M. T. Chakravarty, Gabriele Keller, Simon Peyton Jones, Simon Marlow) POPL '05: Proceedings of the 32nd ACM SIGPLAN-SIGACT sysposium on Principles of programming languages, pages 1--13, Long Beach, California, USA, ACM Press, 2005<br />
<br />
;[http://www.cse.unsw.edu.au/~chak/papers/CKP05.html Associated Type Synonyms]<br />
:Manuel M. T. Chakravarty, Gabriele Keller, and Simon Peyton Jones. In Proceedings of The Tenth ACM SIGPLAN International Conference on Functional Programming, ACM Press, pages 241-253, 2005.<br />
<br />
;[http://www.informatik.uni-freiburg.de/~wehr/diplom ML Modules and Haskell Type Classes: A Constructive Comparison]<br />
:Stefan Wehr Diplomarbeit. Albert-Ludwigs-Universitt Freiburg, Fakultt fr Angewandte Wissenschaften, Institut fr Informatik, November 2005. <br />
<br />
;[http://www.cse.unsw.edu.au/~chak/papers/SCP06.html System F with Type Equality Coercions]<br />
:Martin Sulzmann, Manuel M. T. Chakravarty, and Simon Peyton Jones.<br />
<br />
;[http://www.cs.kuleuven.be/~toms/Research/papers/type_functions.pdf Towards Open Type Functions for Haskell]<br />
:Tom Schrijvers, Simon Peyton Jones, Martin Sulzmann, and Manuel Chakravarty. In Proceedings of IFL' 07, Freiburg, Germany, 2007.<br />
<br />
<br />
==Arbitrary-rank polymorphism==<br />
<br />
;[http://www.ubka.uni-karlsruhe.de/vvv/1996/informatik/81/81.pdf.gz Putting type annotations to work]<br />
:Martin Odersky and Konstantin Läufer. Proceedings of the 23rd ACM SIGPLAN-SIGACT symposium on Principles of programming languages. St. Petersburg Beach, Florida, United States. 54 - 67 1996 ISBN 0-89791-769-3<br />
<br />
;[http://journals.cambridge.org/production/action/cjoGetFulltext%3Ffulltextid%3D445910 Practical type inference for arbitrary-rank types]<br />
:SP Jones, M Shields - Submitted to the Journal of Functional Programming, 2005<br />
<br />
==Phantom types==<br />
<br />
;[http://techreports.library.cornell.edu:8081/Dienst/UI/1.0/Display/cul.cis/TR2003-1901 First-class phantom types]<br />
:James Cheney and Ralf Hinze. Technical Report TR2003-1901, Cornell University, 2003.<br />
<br />
;[http://ttic.uchicago.edu/~fluet/research/phantom-subtyping/jfp06/jfp06.pdf Phantom Types and Subtyping]<br />
:Matthew Fluet and Riccardo Pucella. Submitted to the Journal of Functional Programming, 2006.<br />
<br />
==Implicit parameters==<br />
<br />
;[http://www.cse.ogi.edu/~mbs/pub/implicit_parameters/implicit.ps Implicit Parameters: Dynamic Scoping with Static Types]<br />
:Jeffrey Lewis, Mark Shields, Erik Meijer and John Launchbury. POPL'00. 2000.<br />
<br />
;[http://www.cs.chalmers.se/~rjmh/Globals.ps Global variables in Haskell]<br />
:John Hughes. J. Funct. Program. 14(5): 489-502 (2004) <br />
<br />
;[http://www.cs.uu.nl/pub/RUU/CS/techreps/CS-2004/2004-059.pdf Explicit Implicit Parameters]<br />
:A. Dijkstra and S. D. Swierstra. UU-CS 2004-059, 2004.<br />
<br />
==Object oriented Haskell==<br />
<br />
;[http://research.microsoft.com/~simonpj/Papers/oo-haskell/index.htm Object-Oriented Style Overloading for Haskell] <br />
:Mark Shields and Simon Peyton Jones; BABEL workshop '01.<br />
<br />
;[http://www.cse.unsw.edu.au/~chak/papers/PC03.html Interfacing Haskell with Object-Oriented Languages]<br />
:Andr T. H. Pang and Manuel M. T. Chakravarty. In Greg Michaelson and Phil Trinder, editors, Implementation of Functional Languages: 15th International Workshop, IFL 2003, Edinburgh, UK, September 8-11, 2003, Revised Papers, LNCS 3145, Springer-Verlag, pages 20-36, 2004. <br />
<br />
;[ftp://ftp.cs.chalmers.se/pub/cs-reports/papers/sparud/haskell++.ps.gz Haskell++: An Object-Oriented Extension of Haskell]<br />
:Jan Sparud and John Hughes. Haskell Workshop 1995<br />
<br />
;[http://homepages.cwi.nl/~ralf/OOHaskell/ Haskell's overlooked object system]<br />
:Oleg Kiselyov and Ralf Lämmel, submitted for journal publication; online since 30 Sep. 2004;<br />
<br />
==Restricted Datatypes==<br />
<br />
;[http://www.cs.chalmers.se/~rjmh/Papers/restricted-datatypes.ps Restricted datatypes]<br />
:John Hughes. 1999 Haskell workshop<br />
<br />
==Patterns==<br />
<br />
;[http://www.cs.yale.edu/homes/tullsen/patterns.ps First Class Patterns]<br />
:Mark Tullsen. Practical Aspects of Declarative Languages, Second International Workshop, PADL 2000. volume 1753 of Lecture Notes in Computer Science. January 2000. <br />
<br />
===Pattern guards===<br />
<br />
;[http://research.microsoft.com/~simonpj/Papers/pat.htm Pattern Guards and Transformational Patterns]<br />
:Martin Erwig and Simon Peyton Jones; Haskell Workshop 2000.<br />
<br />
;[http://research.microsoft.com/Users/simonpj/Haskell/guards.html A new view of guards]<br />
:Simon Peyton Jones, April 1997<br />
<br />
===Views===<br />
<br />
;[http://www.haskell.org/development/views.html Views: An Extension to Haskell Pattern Matching]<br />
:Warren Burton, Erik Meijer, Patrick Sansom, Simon Thompson and Phil Wadler.<br />
<br />
;[http://homepages.inf.ed.ac.uk/wadler/papers/view/view.ps.gz Views: A way for pattern matching to cohabit with data abstraction]<br />
:POPL 14 (1987), 307-313.<br />
<br />
==Qualified types==<br />
<br />
;[http://haskell.readscheme.org/servlets/cite.ss?pattern=mpj-jones1994a Qualified Types: Theory and Practice]<br />
:Mark P. Jones. PhD. Thesis. Yale University. November 1994.<br />
<br />
;[http://www.cse.ogi.edu/~mpj/pubs/fpca95.ps Simplifying and Improving Qualified Types]<br />
:Mark P. Jones. FPCA '95: Conference on Functional Programming Languages and Computer Architecture. June 1995.<br />
<br />
;[http://www.cse.ogi.edu/~mpj/pubs/RR-1040.ps Simplifying and Improving Qualified Types]<br />
:Mark P. Jones. Yale University. Research Report YALEU/DCS/RR-1040. June 1994.<br />
<br />
;[http://www.cse.ogi.edu/~mpj/pubs/RR-989.ps Coherence for qualified types]<br />
:Mark P. Jones. Yale University. Research Report YALEU/DCS/RR-989. September 1993. <br />
<br />
;[http://www.cse.ogi.edu/~mpj/pubs/rev-qual-types.ps A theory of qualified types]<br />
:Mark P. Jones. ESOP '92: European Symposium on Programming. Lecture Notes in Computer Science, 582. February 1992. (Cited by 68)<br />
<br />
==Polymorphic recursion==<br />
<br />
;[http://portal.acm.org/citation.cfm%3Fcoll%3DGUIDE%26dl%3DGUIDE%26id%3D169692 Type inference with polymorphic recursion]<br />
:F Henglein - ACM Transactions on Programming Languages and Systems (1993)<br />
<br />
;[http://www.jucs.org/jucs_9_8/practical_type_inference_for/paper.pdf Practical Type Inference for Polymorphic Recursion: an Implementation in Haskell]<br />
:C Vasconcellos, L Figueiredo, C Camarao - Journal of Universal Computer Science, 2003<br />
<br />
;[http://www.dcc.ufmg.br/~camarao/ml0-impl.ps Type Inference for Polymorphic Recursive Definitions: a Specification in Haskell]<br />
:L Figueiredo, C Camarao<br />
<br />
[[Category:Research]]<br />
[[Category:Type-level programming]]</div>Tschrijvershttps://wiki.haskell.org/index.php?title=Research_papers/Type_systems&diff=16860Research papers/Type systems2007-11-15T02:32:44Z<p>Tschrijvers: </p>
<hr />
<div>__TOC__<br />
<br />
==Haskell semantics==<br />
<br />
;[http://research.microsoft.com/~simonpj/Papers/static-semantics.dvi.gz A static semantics for Haskell]<br />
:SL Peyton Jones and PL Wadler, (draft), Department of Computing Science, University of Glasgow, 1992. (Cited by 20)<br />
<br />
;[http://haskell.org/onlinereport/dynamic-semantics.dvi.gz A Dynamic Semantics for Haskell] <br />
:Kevin Hammond and Cordelia Hall, (draft), University of Glasgow, 1992, 23 pages.<br />
<br />
;[http://www.cse.ogi.edu/~mpj/pubs/thih.html Typing Haskell in Haskell] <br />
:Mark P. Jones, In Proceedings of the 1999 Haskell Workshop, Paris, France, October 1999. Published in Technical Report UU-CS-1999-28, Department of Computer Science, University of Utrecht. (Cited by 66)<br />
<br />
;[http://www.pms.informatik.uni-muenchen.de/mitarbeiter/panne/haskell_libs/hsparser.html HParser]<br />
:A parser for Haskell written purely in Haskell (using the Happy parser generator).<br />
<br />
;[http://www.cse.ogi.edu/~hallgren/Talks/LHiH/ A Lexer for Haskell in Haskell]<br />
:Thomas Hallgren, PacSoft Oregon Graduate Institute, 14 January, 2002<br />
<br />
;[http://citeseer.ist.psu.edu/launchbury93natural.html A Natural Semantics for Lazy Evaluation]<br />
:John Launchbury, Conference Record of the Twentieth Annual ACM SIGPLAN-SIGACT Symposium on Principles of Programming Languages, Charleston, South Carolina, 144--154, 1993.<br />
<br />
;[http://www.cs.nott.ac.uk/~gmh/papers/11.ps A Space Semantics for Core Haskell]<br />
:Adam Bakewell. Proc. 2000 Haskell Workshop. September 2001.<br />
<br />
==Pure type systems==<br />
<br />
;[http://research.microsoft.com/~simonpj/Papers/henk.ps.gz Henk: a typed intermediate language]<br />
:SL Peyton Jones and E Meijer, Proceedings of the Types in Compilation Workshop, Amsterdam, June 1997.<br />
<br />
;[http://www.cs.uu.nl/~johanj/MSc/jwroorda/ Pure Type Systems for Functional Programming]<br />
:Jan-Willem Roorda, Masters Thesis, University of Utrecht, INF/SCR-00-13, available online, 2000<br />
<br />
==Dependent Types==<br />
<br />
;[http://www.cs.nott.ac.uk/~txa/publ/ydtm.pdf Why Dependent Types Matter]<br />
:Thorsten Altenkirch and Conor McBride and James McKinna, Manuscript, available online, April, 2005. (Cited by 7)<br />
<br />
;[http://www.informatik.uni-bonn.de/~loeh/LambdaPi.html Simply Easy! An Implementation of a Dependently Typed Lambda Calculus]<br />
:Andres Löh, Conor McBride and Wouter Swierstra, 2007.<br />
<br />
==Unboxed values==<br />
<br />
;[http://www.soi.city.ac.uk/~ross/papers/pointed.html Parametricity and Unboxing with Unpointed Types]<br />
:John Launchbury and Ross Paterson, European Symposium on Programming, LNCS, vol. 1058, pp. 204-218, Springer, Linkping, Sweden, 1996.<br />
<br />
;[http://research.microsoft.com/~simonpj/Papers/unboxed-values.ps.Z Unboxed values as first class citizens]<br />
:SL Peyton Jones and J Launchbury, Functional Programming Languages and Computer Architecture (FPCA'91), Boston, LNCS 523, Springer Verlag, Sept 1991, pp636-666. (Cited by 105)<br />
<br />
==Modules==<br />
<br />
;[http://www.cse.ogi.edu/~diatchki/papers/modules98.pdf A Formal Specification of the Haskell 98 Module System]<br />
:Iavor S. Diatchki, Mark P. Jones, and Thomas Hallgren. Proceedings of the 2002 ACM SIGPLAN workshop on Haskell. Pittsburgh, Pennsylvania. 17 - 28 2002 ISBN 1-58113-605-6 (Cited by 12)<br />
<br />
;[http://research.microsoft.com/~simonpj/Papers/first-class-modules/index.htm First class modules for Haskell]<br />
:Mark Shields and Simon Peyton Jones; FOOL'02.<br />
<br />
;[http://research.microsoft.com/~simonpj/Papers/Nicklisch-modules.ps.gz An exploration of modular programs]<br />
:Electronic proceedings of the 1996 Glasgow Functional Programming Workshop, J Nicklisch and SL Peyton Jones, Ullapool, July 1996.<br />
<br />
==Exceptions==<br />
<br />
;[http://www.haskell.org/~simonmar/papers/ext-exceptions.pdf An Extensible Dynamically-Typed Hierarchy of Exceptions]<br />
:Simon Marlow. Haskell '06: Proceedings of the 2006 ACM SIGPLAN workshop on Haskell, Portland, Oregon, ACM Press, September 2006<br />
<br />
;[http://research.microsoft.com/~simonpj/Papers/imprecise-exn-sem.htm Imprecise Exceptions, Co-Inductively]<br />
:Andy Moran, Soeren Lassen, and Simon Peyton Jones. HOOTS'99.<br />
<br />
;[http://research.microsoft.com/~simonpj/Papers/imprecise-exn.htm A semantics for imprecise exceptions]<br />
:Simon Peyton Jones, Alastair Reid, Tony Hoare, Simon Marlow, Fergus Henderson. Proc Programming Language Design and Implementation (PLDI'99), Atlanta.<br />
<br />
;[http://research.microsoft.com/~simonpj/Papers/asynch-exns.htm Asynchronous exceptions in Haskell]<br />
:Simon Marlow, Simon Peyton Jones, Andy Moran and John Reppy, PLDI'01.<br />
<br />
;[http://www.reid-consulting-uk.ltd.uk/alastair/publications/except6.ps.gz Handling Exceptions in Haskell]<br />
:A. Reid, Research Report YALEU/DCS/RR-1175, Yale University, August, 1998<br />
<br />
==Lexically scoped type variables==<br />
<br />
;[http://research.microsoft.com/%7Esimonpj/papers/scoped%2Dtyvars/ Lexically scoped type variables]<br />
:Simon Peyton Jones and Mark Shields. 2004.<br />
<br />
==Records==<br />
<br />
;[http://research.microsoft.com/~simonpj/Papers/records.htm Lightweight Extensible Records for Haskell]<br />
:Mark Jones and Simon Peyton Jones, Haskell Workshop 1999.<br />
<br />
;[http://www.cs.uu.nl/~daan/download/papers/scopedlabels.pdf Extensible records with scoped labels]<br />
:Daan Leijen. The 2005 Symposium on Trends in Functional Programming (TFP'05), Tallin, Estonia, September 2005.<br />
<br />
;[http://www.cs.uu.nl/~daan/download/papers/fclabels.pdf First-class labels for extensible rows]<br />
:Daan Leijen. Technical Report UU-CS-2004-51, Departement of Computer Science, Universiteit Utrecht, 2004.<br />
<br />
;[http://www.reid-consulting-uk.ltd.uk/alastair/publications/h-wkshop95a/index.html Haskell Records]<br />
:J. Peterson, A. Reid, Proceedings of the Haskell Workshop, La Jolla, June 1995. <br />
<br />
;[http://www.cse.ogi.edu/~mpj/pubs/96-3.ps.gz A Polymorphic Type System for Extensible Records and Variants]<br />
:Benedict R. Gaster and Mark P. Jones. Department of Computer Science, University of Nottingham. Technical report NOTTCS-TR-96-3. November 1996.<br />
<br />
==Meta programming==<br />
<br />
;[http://research.microsoft.com/copyright/accept.asp?path=/users/simonpj/papers/dyntyping.ps.gz&pub=ACM Dynamic typing as staged type inference]<br />
:MB Shields, T Sheard, and SL Peyton Jones, POPL98.<br />
<br />
;[http://research.microsoft.com/~simonpj/Papers/meta-haskell/index.htm Template meta-programming for Haskell]<br />
:Tim Sheard and Simon Peyton Jones, Proceedings of the Haskell Workshop, Pittsburgh, 2002<br />
<br />
;[http://www.cse.unsw.edu.au/~chak/papers/SCK04.html Optimising Embedded DSLs using Template Haskell]<br />
:Sean Seefried, Manuel M. T. Chakravarty, and Gabriele Keller. In Gabor Karsai and Eelco Visser, editors, Third International Conference on Generative Programming and Component Engineering (GPCE'04), LNCS 3286, Springer-Verlag, pages 186-205, 2004. [An earlier draft was presented at the IFL 2003 - 15th International Workshop on the Implementation of Functional Languages, 2003.<br />
<br />
;[http://www.haskell.org/th/papers/Unrolling_and_Simplifying_Expressions_with_Template_Haskell.ps Unrolling and Simplifying Expressions with Template Haskell]<br />
:Ian Lynagh, May 2003.<br />
<br />
;[http://www.haskell.org/th/papers/hlpp.ps Automatic skeletons in Template Haskell]<br />
:Kevin Hammond, Jost Berthold and Rita Loogen, June 2003. Proceedings of 2003 Workshop on High Level Parallel Programming, Paris, France<br />
<br />
;[http://www.haskell.org/th/papers/Typing_Template_Haskell__Soft_Types.ps Typing Template Haskell: Soft Types]<br />
:Ian Lynagh, August 2004.<br />
<br />
==Dynamic typing==<br />
<br />
;[http://www.cs.uu.nl/groups/ST/stbib/swierstra-by-year/BaSw02.bib Typing dynamic typing]<br />
:A. I. Baars and S. D. Swierstra. In S. Peyton Jones, editor, Proceedings of the seventh ACM SIGPLAN international conference on Functional programming, pages 157--166. ACM Press, 2002<br />
<br />
==Parametricity==<br />
<br />
;[http://homepages.inf.ed.ac.uk/wadler/papers/free/free.ps.gz Theorems for free!]<br />
:Philip Wadler. 4'th International Conference on Functional Programming and Computer Architecture, London, September 1989.<br />
<br />
;[http://www.soi.city.ac.uk/~ross/papers/pointed.html Parametricity and Unboxing with Unpointed Types]<br />
:John Launchbury and Ross Paterson, European Symposium on Programming, LNCS, vol. 1058, pp. 204-218, Springer, Linkping, Sweden, 1996.<br />
<br />
;[http://wwwtcs.inf.tu-dresden.de/~voigt/seqFinal.pdf The Impact of seq on Free Theorems-Based Program Transformations]<br />
:Patricia Johann and Janis Voigtländer, Fundamenta Informaticae, vol. 69(1-2), pp. 63-102, 2006.<br />
<br />
==Type classes==<br />
<br />
;[http://homepages.inf.ed.ac.uk/wadler/papers/class/class.ps.gz How to make ad-hoc polymorphism less ad hoc]<br />
:Philip Wadler and Stephen Blott. 16'th Symposium on Principles of Programming Languages, ACM Press, Austin, Texas, January 1989.<br />
<br />
;[http://research.microsoft.com/~simonpj/Papers/classhask.ps.gz Type classes in Haskell, CV Hall, K Hammond, SL Peyton Jones, and PL Wadler]<br />
:European Symposium On Programming, LNCS 788, Springer Verlag, pp. 241-256, April 1994. (Cited by 131)<br />
<br />
;[http://www.cse.ogi.edu/~mpj/pubs/pldi93.html Implementing Type Classes]<br />
:John Peterson and Mark P. Jones, In Proceedings of ACM SIGPLAN Symposium on Programming Language Design and Implementation, ACM SIGPLAN, June 1993. (Cited by 40)<br />
<br />
;[http://www.cs.chalmers.se/pub/cs-reports/papers/overload-fpca-93.ps.Z Implementing Haskell overloading]<br />
:Lennart Augustsson, 1993. FPCA. 65-73<br />
<br />
;[http://web.cecs.pdx.edu/~mpj/pubs/springschool.html Functional Programming with Overloading and Higher-Order Polymorphism]<br />
:Mark P. Jones, First International Spring School on Advanced Functional Programming Techniques, Baastad, Sweden, Springer-Verlag Lecture Notes in Computer Science 925, May 1995.<br />
<br />
;[http://research.microsoft.com/~simonpj/Papers/type-class-design-space Type classes: exploring the design space]<br />
:Simon Peyton Jones, Mark Jones, Erik Meijer, Haskell Workshop 1997.<br />
<br />
;[http://www.cse.ogi.edu/~mpj/pubs/fpca93.html A system of constructor classes: overloading and implicit higher-order polymorphism]<br />
:Mark P. Jones, In FPCA '93: Conference on Functional Programming Languages and Computer Architecture, Copenhagen, Denmark, June 1993.<br />
<br />
;[http://homepages.inf.ed.ac.uk/wadler/papers/overload2/overload2.ps.gz A second look at overloading]<br />
:Martin Odersky, Philip Wadler, Martin Wehr. 7'th International Conference on Functional Programming and Computer Architecture, ACM Press, San Diego, California, June 1995.<br />
<br />
;[http://citeseer.ist.psu.edu/laufer94combining.html Combining Type Classes and Existential Types]<br />
:Konstantin Laufer, Proceedings of the Latin American Informatic Conference (PANEL), 1994<br />
<br />
;[http://citeseer.ifi.unizh.ch/laeufer95type.html Type Classes with Existential Types]<br />
:Konstantin Laufer, Journal of Functional Programming, 1996, May<br />
<br />
;[http://www.cse.unsw.edu.au/~chak/papers/DHCK06.html Modular Type Classes]<br />
:Derek Dreyer, Robert Harper, Manuel M.T. Chakravarty and Gabriele Keller, 2006<br />
<br />
;[http://www.informatik.uni-bonn.de/~ralf/hw2001/4.pdf Named instances for Haskell type classes]<br />
:W Kahl, J Scheffczyk - Proc. Haskell Workshop, 2001 (Cited by 12)<br />
<br />
===Deriving type classes===<br />
<br />
;[http://research.microsoft.com/~simonpj/Papers/derive.htm Derivable Type classes] <br />
:Ralf Hinze and Simon Peyton Jones, Haskell Workshop 2000.<br />
<br />
;[http://www.cis.upenn.edu/~sweirich/RepLib/ RepLib: A Library for Derivable Type Classes]<br />
:Stephanie Weirich 2006<br />
<br />
===Applications of type classes===<br />
<br />
;[http://okmij.org/ftp/Haskell/number-parameterized-types.html Number-parameterized types]<br />
:Oleg Kiselyov, The Monad.Reader. IssueFive. Oct 2nd, 2005<br />
<br />
;[http://web.comlab.ox.ac.uk/oucl/work/jeremy.gibbons/publications/typecase.pdf TypeCase: a design pattern for type-indexed functions]<br />
:Bruno C. d. S. Oliveira, Jeremy Gibbons. Proceedings of the 2005 ACM SIGPLAN workshop on Haskell. Tallinn, Estonia. 98 - 109, 2005 ISBN:1-59593-071-X<br />
<br />
;[http://okmij.org/ftp/Haskell/types.html#Prepose Functional pearl: implicit configurations--or, type classes reflect the values of types]<br />
:Oleg Kiselyov, Chung-chieh Shan, Proceedings of the 2004 ACM SIGPLAN workshop on Haskell, Snowbird, Utah, USA, 2004 ISBN 1-58113-850-4<br />
<br />
;[http://www.comp.nus.edu.sg/~sulzmann/publications/extract-typeclassproofs.pdf Extracting Programs from Type Class Proofs]<br />
:Martin Sulzmann, 2006<br />
<br />
;[http://www.comp.nus.edu.sg/~sulzmann/manuscript/coind-type-class-proofs.ps Co-induction and Type Improvement in Type Class Proofs]<br />
:Martin Sulzmann, Jeremy Wazny and Peter J. Stuckey. 2005<br />
<br />
;[http://www.cs.nott.ac.uk/~ctm/faking.ps.gz Faking It (Simulating Dependent Types in Haskell)]<br />
:Conor McBride, Journal of Functional Programming, 12(4&5):375-392, July 2002<br />
<br />
;[http://www.comp.nus.edu.sg/~sulzmann/manuscript/aophaskell.ps.gz Aspect-Oriented Programming with Type Classes]<br />
:Martin Sulzmann and Meng Wang, 2006.<br />
<br />
==Undecidable instances==<br />
<br />
;[http://www.haskell.org/ghc/docs/6.4.2/html/users_guide/type-extensions.html#undecidable-instances Undecidable instances]<br />
:GHC User's Guide.<br />
<br />
==Multi-parameter type classes==<br />
<br />
;[http://www.comp.nus.edu.sg/~sulzmann/publications/ghc-mptc-inf.ps Principal Type Inference for GHC-Style Multi-Parameter Type Classes]<br />
:Martin Sulzmann, Tom Schrijvers and Peter J. Stuckey. In APLAS'06.<br />
<br />
;[http://www.comp.nus.edu.sg/~sulzmann/manuscript/mptc-inf-old.pdf Type Inference for Multi-Parameter Type Classes]<br />
:Martin Sulzmann and Peter J. Stuckey. 2005<br />
<br />
;[http://ostrich.lcs.mit.edu/cgi-bin/pickbib?jfp::DugganO2002 Type-checking multi-parameter type classes]<br />
:Dominic Duggan and John Ophel, Journal of Functional Programming, 12(2):133-158, March 2002<br />
<br />
==Functional dependencies==<br />
<br />
;[http://www.cse.ogi.edu/~mpj/pubs/fundeps.html Type Classes with Functional Dependencies]<br />
:Mark P. Jones, In Proceedings of the 9th European Symposium on Programming, ESOP 2000, Berlin, Germany, March 2000, Springer-Verlag LNCS 1782.<br />
<br />
;[http://research.microsoft.com/~simonpj/Papers/fd-chr/index.htm Sound and Decidable Type Inference for Functional Dependencies]<br />
:Gregory J. Duck, Simon Peyton Jones, Peter J. Stuckey, and Martin Sulzmann, European Symposium on Programming 2004 (ESOP'04).<br />
<br />
;[http://www.comp.nus.edu.sg/~sulzmann/publications/jfp-fds-revised.pdf Understanding Functional Dependencies via Constraint Handling Rules]<br />
:Martin Sulzmann, Gregory J. Duck, Simon Peyton-Jones and Peter J. Stuckey.j To appear in Journal of Functional Programming. 2006<br />
<br />
;[http://www.comp.nus.edu.sg/~sulzmann/manuscript/afds.ps Associated Functional Dependencies]<br />
:Martin Sulzmann and Edmund Soon Lee Lam. 2005<br />
<br />
==Constraint Handling Rules==<br />
<br />
;[http://www.comp.nus.edu.sg/~sulzmann/publications/aplas06-invited.pdf Type Processing by Constraint Reasoning]<br />
:Peter J. Stuckey, Martin Sulzmann and Jeremy Wazny, In APLAS'06.<br />
<br />
;[http://www.comp.nus.edu.sg/~sulzmann/manuscript/chr-stm.ps A Concurrent Constraint Handling Rules Implementation in Haskell with Software Transactional Memory]<br />
:Edmund S.L. Lam and Martin Sulzmann<br />
<br />
;[http://www.comp.nus.edu.sg/~sulzmann/publications/chr06-observable.ps Observable Confluence for Constraint Handling Rules]<br />
:Gregory J. Duck, Peter J. Stuckey and Martin Sulzmann<br />
<br />
==Generalised Algebraic Data Types (GADTs)==<br />
<br />
;[http://research.microsoft.com/~simonpj/papers/gadt/index.htm Simple unification-based type inference for GADTs]<br />
:Simon Peyton Jones, Dimitrios Vytiniotis, Stephanie Weirich, and Geoffrey Washburn. Submitted to PLDI 2005<br />
<br />
;[http://www.cis.upenn.edu/~geoffw/research/papers/MS-CIS-05-26.pdf Wobbly types: type inference for generalised algebraic data types]<br />
:S Peyton Jones, G. Washburn, and S. Weirich. 2004.<br />
<br />
;[http://www.comp.nus.edu.sg/~sulzmann/manuscript/simple-translate-gadts.ps Translating Generalized Algebraic Data Types to System F]<br />
:Martin Sulzmann and Meng Wang. 2005<br />
<br />
;[http://cristal.inria.fr/~fpottier/publis/pottier-regis-gianas-05.pdf Stratified type inference for generalized algebraic data types]<br />
:François Pottier and Yann Régis-Gianas, 2006<br />
<br />
;[http://www.comp.nus.edu.sg/~sulzmann/manuscript/gadt-short.ps Type Inference for GADTs via Herbrand Constraint Abduction]<br />
:Martin Sulzmann, Tom Schrijvers and Peter J. Stuckey, 2006 <br />
<br />
;[http://www.comp.nus.edu.sg/~sulzmann/publications/tr-eadt.ps.gz A Framework for Extended Algebraic Data Types]<br />
:Martin Sulzmann, Jeremy Wazny and Peter J. Stuckey, 2006<br />
<br />
See also the [[GADT]] page.<br />
<br />
==Parametric Regular Data Types==<br />
<br />
;[http://www.comp.nus.edu.sg/~sulzmann/manuscript/parametric-regular.ps Type Inference and Compilation for Parametric Regular Data Types]<br />
:Martin Sulzmann and Kenny Zhuo Ming Lu, 2006<br />
<br />
;[http://www.comp.nus.edu.sg/~sulzmann/manuscript/haskell-xduce.ps The Marriage of Haskell and XDuce]<br />
:Martin Sulzmann and Kenny Zhuo Ming Lu<br />
<br />
==Associated types==<br />
<br />
;[http://www.haskell.org/~simonmar/papers/assoc.pdf Associated types with class]<br />
:Manuel M. T. Chakravarty, Gabriele Keller, Simon Peyton Jones, Simon Marlow) POPL '05: Proceedings of the 32nd ACM SIGPLAN-SIGACT sysposium on Principles of programming languages, pages 1--13, Long Beach, California, USA, ACM Press, 2005<br />
<br />
;[http://www.cse.unsw.edu.au/~chak/papers/CKP05.html Associated Type Synonyms]<br />
:Manuel M. T. Chakravarty, Gabriele Keller, and Simon Peyton Jones. In Proceedings of The Tenth ACM SIGPLAN International Conference on Functional Programming, ACM Press, pages 241-253, 2005.<br />
<br />
;[http://www.informatik.uni-freiburg.de/~wehr/diplom ML Modules and Haskell Type Classes: A Constructive Comparison]<br />
:Stefan Wehr Diplomarbeit. Albert-Ludwigs-Universitt Freiburg, Fakultt fr Angewandte Wissenschaften, Institut fr Informatik, November 2005. <br />
<br />
;[http://www.cse.unsw.edu.au/~chak/papers/SCP06.html System F with Type Equality Coercions]<br />
:Martin Sulzmann, Manuel M. T. Chakravarty, and Simon Peyton Jones.<br />
<br />
;[http://www.cs.kuleuven.be/~toms/Research/papers/type_functions.pdf Towards Open Type Functions for Haskell]<br />
:Tom Schrijvers, Simon Peyton Jones, Martin Sulzmann, and Manuel Chakravarty.<br />
In Proceedings of IFL' 07, Freiburg, Germany, 2007.<br />
<br />
<br />
==Arbitrary-rank polymorphism==<br />
<br />
;[http://www.ubka.uni-karlsruhe.de/vvv/1996/informatik/81/81.pdf.gz Putting type annotations to work]<br />
:Martin Odersky and Konstantin Läufer. Proceedings of the 23rd ACM SIGPLAN-SIGACT symposium on Principles of programming languages. St. Petersburg Beach, Florida, United States. 54 - 67 1996 ISBN 0-89791-769-3<br />
<br />
;[http://journals.cambridge.org/production/action/cjoGetFulltext%3Ffulltextid%3D445910 Practical type inference for arbitrary-rank types]<br />
:SP Jones, M Shields - Submitted to the Journal of Functional Programming, 2005<br />
<br />
==Phantom types==<br />
<br />
;[http://techreports.library.cornell.edu:8081/Dienst/UI/1.0/Display/cul.cis/TR2003-1901 First-class phantom types]<br />
:James Cheney and Ralf Hinze. Technical Report TR2003-1901, Cornell University, 2003.<br />
<br />
;[http://ttic.uchicago.edu/~fluet/research/phantom-subtyping/jfp06/jfp06.pdf Phantom Types and Subtyping]<br />
:Matthew Fluet and Riccardo Pucella. Submitted to the Journal of Functional Programming, 2006.<br />
<br />
==Implicit parameters==<br />
<br />
;[http://www.cse.ogi.edu/~mbs/pub/implicit_parameters/implicit.ps Implicit Parameters: Dynamic Scoping with Static Types]<br />
:Jeffrey Lewis, Mark Shields, Erik Meijer and John Launchbury. POPL'00. 2000.<br />
<br />
;[http://www.cs.chalmers.se/~rjmh/Globals.ps Global variables in Haskell]<br />
:John Hughes. J. Funct. Program. 14(5): 489-502 (2004) <br />
<br />
;[http://www.cs.uu.nl/pub/RUU/CS/techreps/CS-2004/2004-059.pdf Explicit Implicit Parameters]<br />
:A. Dijkstra and S. D. Swierstra. UU-CS 2004-059, 2004.<br />
<br />
==Object oriented Haskell==<br />
<br />
;[http://research.microsoft.com/~simonpj/Papers/oo-haskell/index.htm Object-Oriented Style Overloading for Haskell] <br />
:Mark Shields and Simon Peyton Jones; BABEL workshop '01.<br />
<br />
;[http://www.cse.unsw.edu.au/~chak/papers/PC03.html Interfacing Haskell with Object-Oriented Languages]<br />
:Andr T. H. Pang and Manuel M. T. Chakravarty. In Greg Michaelson and Phil Trinder, editors, Implementation of Functional Languages: 15th International Workshop, IFL 2003, Edinburgh, UK, September 8-11, 2003, Revised Papers, LNCS 3145, Springer-Verlag, pages 20-36, 2004. <br />
<br />
;[ftp://ftp.cs.chalmers.se/pub/cs-reports/papers/sparud/haskell++.ps.gz Haskell++: An Object-Oriented Extension of Haskell]<br />
:Jan Sparud and John Hughes. Haskell Workshop 1995<br />
<br />
;[http://homepages.cwi.nl/~ralf/OOHaskell/ Haskell's overlooked object system]<br />
:Oleg Kiselyov and Ralf Lämmel, submitted for journal publication; online since 30 Sep. 2004;<br />
<br />
==Restricted Datatypes==<br />
<br />
;[http://www.cs.chalmers.se/~rjmh/Papers/restricted-datatypes.ps Restricted datatypes]<br />
:John Hughes. 1999 Haskell workshop<br />
<br />
==Patterns==<br />
<br />
;[http://www.cs.yale.edu/homes/tullsen/patterns.ps First Class Patterns]<br />
:Mark Tullsen. Practical Aspects of Declarative Languages, Second International Workshop, PADL 2000. volume 1753 of Lecture Notes in Computer Science. January 2000. <br />
<br />
===Pattern guards===<br />
<br />
;[http://research.microsoft.com/~simonpj/Papers/pat.htm Pattern Guards and Transformational Patterns]<br />
:Martin Erwig and Simon Peyton Jones; Haskell Workshop 2000.<br />
<br />
;[http://research.microsoft.com/Users/simonpj/Haskell/guards.html A new view of guards]<br />
:Simon Peyton Jones, April 1997<br />
<br />
===Views===<br />
<br />
;[http://www.haskell.org/development/views.html Views: An Extension to Haskell Pattern Matching]<br />
:Warren Burton, Erik Meijer, Patrick Sansom, Simon Thompson and Phil Wadler.<br />
<br />
;[http://homepages.inf.ed.ac.uk/wadler/papers/view/view.ps.gz Views: A way for pattern matching to cohabit with data abstraction]<br />
:POPL 14 (1987), 307-313.<br />
<br />
==Qualified types==<br />
<br />
;[http://haskell.readscheme.org/servlets/cite.ss?pattern=mpj-jones1994a Qualified Types: Theory and Practice]<br />
:Mark P. Jones. PhD. Thesis. Yale University. November 1994.<br />
<br />
;[http://www.cse.ogi.edu/~mpj/pubs/fpca95.ps Simplifying and Improving Qualified Types]<br />
:Mark P. Jones. FPCA '95: Conference on Functional Programming Languages and Computer Architecture. June 1995.<br />
<br />
;[http://www.cse.ogi.edu/~mpj/pubs/RR-1040.ps Simplifying and Improving Qualified Types]<br />
:Mark P. Jones. Yale University. Research Report YALEU/DCS/RR-1040. June 1994.<br />
<br />
;[http://www.cse.ogi.edu/~mpj/pubs/RR-989.ps Coherence for qualified types]<br />
:Mark P. Jones. Yale University. Research Report YALEU/DCS/RR-989. September 1993. <br />
<br />
;[http://www.cse.ogi.edu/~mpj/pubs/rev-qual-types.ps A theory of qualified types]<br />
:Mark P. Jones. ESOP '92: European Symposium on Programming. Lecture Notes in Computer Science, 582. February 1992. (Cited by 68)<br />
<br />
==Polymorphic recursion==<br />
<br />
;[http://portal.acm.org/citation.cfm%3Fcoll%3DGUIDE%26dl%3DGUIDE%26id%3D169692 Type inference with polymorphic recursion]<br />
:F Henglein - ACM Transactions on Programming Languages and Systems (1993)<br />
<br />
;[http://www.jucs.org/jucs_9_8/practical_type_inference_for/paper.pdf Practical Type Inference for Polymorphic Recursion: an Implementation in Haskell]<br />
:C Vasconcellos, L Figueiredo, C Camarao - Journal of Universal Computer Science, 2003<br />
<br />
;[http://www.dcc.ufmg.br/~camarao/ml0-impl.ps Type Inference for Polymorphic Recursive Definitions: a Specification in Haskell]<br />
:L Figueiredo, C Camarao<br />
<br />
[[Category:Research]]<br />
[[Category:Type-level programming]]</div>Tschrijvershttps://wiki.haskell.org/index.php?title=Research_papers/Authors&diff=16859Research papers/Authors2007-11-15T02:26:46Z<p>Tschrijvers: </p>
<hr />
<div>__NOTOC__<br />
<br />
==A==<br />
*[http://www.tcs.informatik.uni-muenchen.de/~abel/ Andres Abel]<br />
*[http://www.cs.nott.ac.uk/~txa/publ/ Thorsten Altenkirch]<br />
*[http://homepages.cwi.nl/~atanasso/pub Frank Atanassow]<br />
*[http://www.cs.chalmers.se/~augustss/ Lennart Augustsson]<br />
<br />
==B==<br />
*[http://www.cs.uu.nl/groups/ST/stbib/baars-by-year/baars-by-year-by-year.html Arthur Baars]<br />
*[http://web.comlab.ox.ac.uk/oucl/work/richard.bird/publications.html Richard Bird]<br />
*[http://www.cs.chalmers.se/~bjesse/ Per Bjesse]<br />
*[http://www.cs.chalmers.se/~boquist/ Urban Boquist]<br />
*[http://www.dcs.gla.ac.uk/~bunkenba/ Alex Bunkenburg]<br />
*[http://www.cs.sfu.ca/people/Faculty/Burton/publications.html F. Warren Burton]<br />
<br />
==C==<br />
*[http://www.cse.ogi.edu/~magnus/ Magnus Carlsson]<br />
*[http://www.cse.unsw.edu.au/~chak/papers/papers.html Manuel M. T. Chakravarty]<br />
*[http://www.cs.kent.ac.uk/people/staff/oc/pubs.html Olaf Chitil]<br />
*[http://www.iis.sinica.edu.tw/~trc/node2.html Tyng-Ruey Chuang]<br />
*[http://www.cs.chalmers.se/~koen/pubs/ Koen Claessen]<br />
*[http://www.dcs.gla.ac.uk/~grmc/ Graham Collins]<br />
*[http://www.irisa.fr/EXTERNE/projet/lande/consel/consel.html Charles Consel]<br />
*[http://www.apocalypse.org/pub/u/antony/work/index.html Antony Courtney]<br />
<br />
==D==<br />
*[http://www.c3.lanl.gov/~kei/publications.html Kei Davis]<br />
*[http://www.cse.ogi.edu/~diatchki/papers/ Iavor Diatchki]<br />
<br />
==E==<br />
*[http://conal.net/papers/ Conal Elliott]<br />
*[http://www.cambridge.intel-research.net/~rennals/ Robert Ennals]<br />
*[http://web.engr.oregonstate.edu/~erwig/papers/ Martin Erwig]<br />
<br />
==F==<br />
*[http://web.it.kth.se/~kff/publications.html Karl-Filip Fax&eacute;n]<br />
*[http://yeats.ucc.ie/~abf/ Alex Ferguson]<br />
*[http://www.galois.com/~sof/pubs.html Sigbjorn Finne]<br />
*[http://www.cs.uu.nl/people/jeroen/ Jeroen Fokker]<br />
<br />
==G==<br />
*[http://web.comlab.ox.ac.uk/oucl/work/jeremy.gibbons/publications/ Jeremy Gibbons]<br />
*[http://www.gill-warbington.com/home/andy/ Andy Gill]<br />
*[http://www.dcs.gla.ac.uk/~joy/ Joy Goodman]<br />
*[http://research.microsoft.com/~adg/ Andrew D. Gordon]<br />
*Louis-Julien Guillemette<br />
*[http://www.cs.chalmers.se/~gustavss/ J&ouml;rgen Gustavsson]<br />
<br />
==H==<br />
*[http://www.dcs.gla.ac.uk/~cvh/ Cordelia Hall]<br />
*[http://www.cse.ogi.edu/~hallgren/ Thomas Hallgren]<br />
*[http://www-fp.dcs.st-and.ac.uk/~kh/papers/ABSTRACTS.html Kevin Hammond]<br />
*[http://research.microsoft.com/~tharris/ Tim Harris]<br />
*[http://www.cs.uu.nl/~bastiaan/ Bastiaan Heeren]<br />
*[http://www.cs.chalmers.se/~heldal/ Rogardt Heldal]<br />
*[http://www.cs.unc.edu/~heringto/ Dean Herington]<br />
*[http://www.infosun.fmi.uni-passau.de/cl/staff/herrmann/index.html Christoph A. Herrmann]<br />
*[http://www.informatik.uni-bonn.de/~ralf/publications/ Ralf Hinze]<br />
*[http://www.cs.uu.nl/people/stefan Stefan Holdermans]<br />
*[http://www.cse.ogi.edu/~hook/new/Default.htm James Hook]<br />
*[http://www.ipl.t.u-tokyo.ac.jp/~hu/pub/tech.html Zhenjiang Hu]<br />
*[http://cs-www.cs.yale.edu/homes/hudak.html Paul Hudak]<br />
*[http://www.cs.chalmers.se/~rjmh/pubs.htm John Hughes]<br />
*[http://www.cs.nott.ac.uk/~gmh/ Graham Hutton]<br />
<br />
==I==<br />
*[http://www.cs.nott.ac.uk/Department/Staff/gmh/bib.html Graham Hutton]<br />
*[http://www.cs.uu.nl/groups/ST/stbib/ijzendoorn-by-year/ijzendoorn-by-year-by-year.html Arjan van IJzendoorn]<br />
*[http://www.cs.chalmers.se/~indrika/ Mia Indrika]<br />
<br />
==J==<br />
*[http://www.cs.chalmers.se/~patrikj/ Patrik Jansson]<br />
*[http://www.cs.uu.nl/groups/ST/stbib/jeuring-by-year/jeuring-by-year-by-year.html Johan Jeuring]<br />
*[http://crab.rutgers.edu/~pjohann/vita.html Patricia Johann]<br />
*[http://www.cs.chalmers.se/~bengtj/ Bengt Johansson]<br />
*[http://www.cs.chalmers.se/~johnsson Thomas Johnsson]<br />
*[http://web.cecs.pdx.edu/~mpj/pubs.html Mark P. Jones]<br />
*[http://www.cs.stir.ac.uk/~sbj/ Simon B. Jones]<br />
*[http://research.microsoft.com/Users/simonpj Simon Peyton Jones]<br />
*[http://www.syntaxpolice.org/ Isaac Jones]<br />
<br />
==K==<br />
*[http://users.info.unicaen.fr/~karczma Jerzy Karczmarczuk]<br />
*[http://www.cse.unsw.edu.au/~keller/#publications Gabriele Keller]<br />
*[http://okmij.org/ftp/ Oleg Kiselyov]<br />
*[http://www.cse.ogi.edu/~krstic/ Sava Krstic]<br />
<br />
==L==<br />
*[http://lsi.uniovi.es/~labra Jose E. Labra]<br />
*[http://homepages.cwi.nl/~ralf/publications.html Ralf Lämmel]<br />
*[http://www.cse.ogi.edu/~jl John Launchbury]<br />
*[http://www.cs.uu.nl/~daan/pubs.html Daan Leijen]<br />
*[http://www.cse.ogi.edu/~jlewis Jeff Lewis]<br />
*[http://www.seas.upenn.edu/~lipeng/homepage/ Peng Li]<br />
*[http://java.sun.com/people/sl/ Sheng Liang]<br />
*[http://www.iai.uni-bonn.de/~loeh Andres L&ouml;h]<br />
*[http://www.dcs.gla.ac.uk/~hwloidl/ Hans-Wolfgang Loidl]<br />
*[http://www.mathematik.uni-marburg.de/~loogen Rita Loogen]<br />
*[http://www.frogsonice.com/work.html Sandra J. Loosemore]<br />
*[http://web.comlab.ox.ac.uk/oucl/work/ian.lynagh/papers/ Ian Lynagh]<br />
<br />
==M==<br />
*[http://www.haskell.org/~simonmar/bib/bib.html Simon Marlow] <br />
*[http://www.cs.nott.ac.uk/~ctm/publications.html Conor McBride]<br />
*[http://www.dcs.st-andrews.ac.uk/~james/ James McKinna]<br />
*[http://www.kestrel.edu/home/people/meertens/ Lambert Meertens]<br />
*[http://research.microsoft.com/~emeijer/ Eric Meijer]<br />
*[http://www.engr.uconn.edu/~jeffm/ Jeff Meunier]<br />
*[http://www-users.cs.york.ac.uk/~ndm/downloads.php Neil Mitchell]<br />
*[http://www.disi.unige.it/person/MoggiE/publications.html Eugenio Moggi]<br />
*Andrew Moran<br />
*Stefan Monnier<br />
<br />
==N==<br />
*[http://cs-www.cs.yale.edu/homes/nilsson/papers.html Henrik Nilsson]<br />
*[http://www.cse.ogi.edu/~nordin Thomas Nordin]<br />
*[http://www.cse.ogi.edu/~nordland/ Johan Nordlander]<br />
<br />
==O==<br />
*[http://lampwww.epfl.ch/~odersky/papers/ Martin Odersky]<br />
*[http://www.dcs.gla.ac.uk/~jtod/ John O'Donnell]<br />
*[http://www.eecs.usma.edu/Personnel/okasaki Chris Okasaki]<br />
*[http://www.ipl.t.u-tokyo.ac.jp/~onoue/ Yoshiyuki Onoue]<br />
<br />
==P==<br />
*[http://www.cs.chalmers.se/~pareto/ Lars Pareto]<br />
*[http://www.dcs.gla.ac.uk/~partain/ Will Partain]<br />
*[http://www.soi.city.ac.uk/~ross/papers/ Ross Paterson]<br />
*[[User:John Peterson|John Peterson]]<br />
*[http://research.microsoft.com/Users/simonpj Simon Peyton Jones]<br />
*[http://www.cs.mu.oz.au/~bjpop/papers.html Bernie Pope]<br />
*[http://www.mathematik.uni-marburg.de/~priebe Steffen Priebe]<br />
<br />
==Q==<br />
<br />
==R==<br />
*[http://www.reid-consulting-uk.ltd.uk/alastair/ Alastair Reid]<br />
*[http://www.dcs.gla.ac.uk/~reidrm/ Richard Reid]<br />
*[http://www.dcs.gla.ac.uk/~reig/ Fermin Reig]<br />
*[http://www-users.cs.york.ac.uk/~colin/ Colin Runciman]<br />
<br />
==S==<br />
*[http://www.cs.chalmers.se/~andrei/ Andrei Sabelfeld]<br />
*[http://www.dcs.gla.ac.uk/~meurig/ Meurig Sage]<br />
*[http://www.cs.chalmers.se/~dave/ David Sands]<br />
*[http://www.dcs.gla.ac.uk/~sansom/ Patrick Sansom]<br />
*[http://www.di.ufpe.br/~alms/ Andr&eacute; Santos]<br />
*[http://www.cs.kuleuven.be/~toms/ Tom Schrijvers]<br />
*[http://www.cse.unsw.edu.au/~sseefried/papers/papers.html Sean Seefried]<br />
*[http://web.cecs.pdx.edu/~sheard/papers/ Tim Sheard]<br />
*[http://www.cs.chalmers.se/~ms/ Mary Sheeran]<br />
*[http://www.cse.ogi.edu/~mbs/ Mark Shields]<br />
*[http://www.dis.strath.ac.uk/people/sinclair/ Duncan Sinclair]<br />
*[http://www.xilinx.com/labs/satnam Satnam Singh]<br />
*[http://www.cs.chalmers.se/~sparud/ Jan Sparud]<br />
*[http://www.cs.bris.ac.uk/~spilio/ Eleni Spiliopoulou]<br />
*[http://www.cse.unsw.edu.au/~dons/papers.html Don Stewart]<br />
*[http://www.comp.nus.edu.sg/~sulzmann/ Martin Sulzmann]<br />
*[http://www.cs.chalmers.se/~josefs/ Josef Svenningsson]<br />
*[http://www.cs.uu.nl/groups/ST/stbib/swierstra-by-year/swierstra-by-year-by-year.html Doaitse Swierstra]<br />
<br />
==T==<br />
*[http://www.cs.chalmers.se/~makoto Makoto Takeyama]<br />
*[http://www.math.uni-bremen.de/~thielema/ResearchE.html Henning Thielemann]<br />
*[http://www.cs.kent.ac.uk/people/staff/sjt/pubs.html Simon Thompson]<br />
*[http://www.cs.york.ac.uk/~mjt/ Michael Thyer]<br />
*[http://www.macs.hw.ac.uk/~trinder/publications.html Paul Trinder]<br />
*[http://www.cs.yale.edu/homes/tullsen/publications.html Mark Tullsen]<br />
<br />
==U==<br />
<br />
* [http://www.cs.ioc.ee/~tarmo/papers/ Tarmo Uustalu]<br />
<br />
==V==<br />
* [http://www.cs.ru.nl/A.vanWeelden/index.php?p=publications Arjen van Weelden]<br />
* [http://www.cs.ut.ee/~varmo/papers/index.html Varmo Vene]<br />
* [http://wwwtcs.inf.tu-dresden.de/~voigt/ Janis Voigtländer]<br />
<br />
==W==<br />
*[http://homepages.inf.ed.ac.uk/wadler/ Philip Wadler]<br />
*[ftp://ftp.cs.york.ac.uk/pub/malcolm/ Malcolm Wallace]<br />
*[http://www.lochan.org/keith/publications/index.html Keith Wansbrough]<br />
*[http://www.cis.upenn.edu/~geoffw/research/index.html Geoff Washburn]<br />
*[http://www.seas.upenn.edu/%7Esweirich/publications.html Stephanie Weirich]<br />
*[http://www.informatik.uni-freiburg.de/~wehr/#Publications Stefan Wehr]<br />
*[http://www.lotus.com/lotus/research.nsf/grouppage?Openpage Eric Wilcox]<br />
*[http://www.dcs.gla.ac.uk/~nww/ Noel Winstanley]<br />
<br />
==X==<br />
*[http://www.cl.cam.ac.uk/~nx200/ Dana Xu]<br />
<br />
==Y==<br />
<br />
==Z==<br />
<br />
<i>Authors, please add yourself! :)</i></div>Tschrijvershttps://wiki.haskell.org/index.php?title=GHC/Type_families&diff=13225GHC/Type families2007-05-25T14:11:44Z<p>Tschrijvers: </p>
<hr />
<div>[[Category:GHC|Indexed types]]<br />
== Data and type families in GHC ==<br />
<br />
Data and type families are a new addition to GHC's type extensions. They are currently an '''experimental''' feature and so their design may still change to some degree. The current implementation covers ''data families'' (including newtypes), which can either be on the toplevel or inside class declarations - the latter are also known as [http://www.cse.unsw.edu.au/~chak/papers/CKPM05.html associated data types]. <br />
<br />
'''NB:''' Please note that type families (and hence also associated type synonyms) are '''not''' fully implemented yet. Any attempt to use them will lead to strange error messages. For the moment, you can only use <hask>data</hask> families.<br />
<br />
== What do I need to use data families? ==<br />
<br />
Indexed type families are implemented in GHC's HEAD (from version 6.7), which you can obtain in binary form from the [http://www.haskell.org/ghc/dist/current/dist/ nightly snapshots] or in source form from the [http://hackage.haskell.org/trac/ghc/wiki/Building/GettingTheSources source repository]. To enable indexed type families in GHC 6.7, you need to supply the compiler option <tt>-ftype-families</tt> (or <tt>-fglasgow-exts</tt>, which implies it). NB: The option used to be called <tt>-findexed-types</tt> for a while.<br />
<br />
== An associated data type example ==<br />
<br />
As an example, consider Ralf Hinze's [http://www.informatik.uni-bonn.de/~ralf/publications.html#J4 generalised tries], a form of generic finite maps. <br />
<br />
=== The class declaration ===<br />
<br />
We define a type class whose instances are the types that we can use as keys in our generic maps:<br />
<haskell><br />
class GMapKey k where<br />
data GMap k :: * -> *<br />
empty :: GMap k v<br />
lookup :: k -> GMap k v -> Maybe v<br />
insert :: k -> v -> GMap k v -> GMap k v<br />
</haskell><br />
The interesting part is the ''associated data family'' declaration of the class. It gives a [http://www.haskell.org/ghc/docs/latest/html/users_guide/type-extensions.html#sec-kinding ''kind signature''] (here <hask>* -> *</hask>) for the associated data type <hask>GMap k</hask> - analog to how methods receive a type signature in a class declaration.<br />
<br />
What it is important to notice is that the first parameter of the associated type <hask>GMap</hask> coincides with the class parameter of <hask>GMapKey</hask>. This indicates that also in all instances of the class, the instances of the associated data type need to have their first argument match up with the instance type. In general, the type arguments of an associated type can be a subset of the class parameters (in a multi-parameter type class) and they can appear in any order, possibly in an order other than in the class head. The latter can be useful if the associated data type is partially applied in some contexts.<br />
<br />
The second important point is that as <hask>GMap k</hask> has kind <hask>* -> *</hask> and <hask>k</hask> (implicitly) has kind <hask>*</hask>, the type constructor <hask>GMap</hask> (without an argument) has kind <hask>* -> * -> *</hask>. Consequently, we see that <hask>GMap</hask> is applied to two arguments in the signatures of the methods <hask>empty</hask>, <hask>lookup</hask>, and <hask>insert</hask>.<br />
<br />
=== An Int instance ===<br />
<br />
To use Ints as keys into generic maps, we declare an instance that simply uses <hask>Data.Map</hask>, thusly:<br />
<haskell><br />
instance GMapKey Int where<br />
data GMap Int v = GMapInt (Data.Map.Map Int v)<br />
empty = GMapInt Data.Map.empty<br />
lookup k (GMapInt m) = Data.Map.lookup k m<br />
insert k v (GMapInt m) = GMapInt (Data.Map.insert k v m)<br />
</haskell><br />
The <hask>Int</hask> instance of the associated data type <hask>GMap</hask> needs to have both of its parameters, but as only the first one corresponds to a class parameter, the second needs to be a type variable (here <hask>v</hask>). As mentioned before any associated type parameter that corresponds to a class parameter must be identical to the class parameter in each instance. The right hand side of the associated data declaration is like that of any other data type.<br />
<br />
NB: At the moment, GADT syntax is not allowed for associated data types (or other indexed types). This is not a fundemental limitation, but just a shortcoming of the current implementation, which we expect to lift in the future.<br />
<br />
As an exercise, implement an instance for <hask>Char</hask> that maps back to the <hask>Int</hask> instance using the conversion functions <hask>Char.ord</hask> and <hask>Char.chr</hask>.<br />
<br />
=== A unit instance ===<br />
<br />
Generic definitions, apart from elementary types, typically cover units, products, and sums. We start here with the unit instance for <hask>GMap</hask>:<br />
<haskell><br />
instance GMapKey () where<br />
data GMap () v = GMapUnit (Maybe v)<br />
empty = GMapUnit Nothing<br />
lookup () (GMapUnit v) = v<br />
insert () v (GMapUnit _) = GMapUnit $ Just v<br />
</haskell><br />
For unit, the map is just a <hask>Maybe</hask> value.<br />
<br />
=== Product and sum instances ===<br />
<br />
Nest, let us define the instances for pairs and sums (i.e., <hask>Either</hask>):<br />
<haskell><br />
instance (GMapKey a, GMapKey b) => GMapKey (a, b) where<br />
data GMap (a, b) v = GMapPair (GMap a (GMap b v))<br />
empty = GMapPair empty<br />
lookup (a, b) (GMapPair gm) = lookup a gm >>= lookup b <br />
insert (a, b) v (GMapPair gm) = GMapPair $ case lookup a gm of<br />
Nothing -> insert a (insert b v empty) gm<br />
Just gm2 -> insert a (insert b v gm2 ) gm<br />
<br />
instance (GMapKey a, GMapKey b) => GMapKey (Either a b) where<br />
data GMap (Either a b) v = GMapEither (GMap a v) (GMap b v)<br />
empty = GMapEither empty empty<br />
lookup (Left a) (GMapEither gm1 _gm2) = lookup a gm1<br />
lookup (Right b) (GMapEither _gm1 gm2 ) = lookup b gm2<br />
insert (Left a) v (GMapEither gm1 gm2) = GMapEither (insert a v gm1) gm2<br />
insert (Right a) v (GMapEither gm1 gm2) = GMapEither gm1 (insert a v gm2)<br />
</haskell><br />
If you find this code algorithmically surprising, I'd suggest to have a look at [http://www.informatik.uni-bonn.de/~ralf/publications.html#J4 Ralf Hinze's paper]. The only novelty concerning associated types, in these two instances, is that the instances have a context <hask>(GMapKey a, GMapKey b)</hask>. Consequently, the right hand sides of the associated type declarations can use <hask>GMap</hask> recursively at the key types <hask>a</hask> and <hask>b</hask> - not unlike the method definitions use the class methods recursively at the types for which the class is given in the instance context.<br />
<br />
=== Using a generic map ===<br />
<br />
Finally, some code building and quering a generic map:<br />
<haskell><br />
myGMap :: GMap (Int, Either Char ()) String<br />
myGMap = insert (5, Left 'c') "(5, Left 'c')" $<br />
insert (4, Right ()) "(4, Right ())" $<br />
insert (5, Right ()) "This is the one!" $<br />
insert (5, Right ()) "This is the two!" $<br />
insert (6, Right ()) "(6, Right ())" $<br />
insert (5, Left 'a') "(5, Left 'a')" $<br />
empty<br />
main = putStrLn $ maybe "Couldn't find key!" id $ lookup (5, Right ()) myGMap<br />
</haskell><br />
<br />
=== Download the code ===<br />
<br />
If you want to play with this example without copying it off the wiki, just download the [http://darcs.haskell.org/testsuite/tests/ghc-regress/indexed-types/should_run/GMapAssoc.hs source code for <hask>GMap</hask>] from GHC's test suite.<br />
<br />
== Definition of the type system extension ==<br />
<br />
['''NB:''' The following material will eventually become documentation for type families in the GHC User Manual. Please help to improve it by forwarding suggestions to <tt>chak@cse.unsw.edu.au</tt>.]<br />
<br />
Data families appear in two flavours: (1) they can be defined on the toplevel or (2) they can appear inside type classes (in which case they are known as associated types). The former is the more general variant, as it lacks the requirement for the type-indexes to coincide with the class parameters. However, the later can lead to more clearly structured code and compiler warnings if some type instances were - possibly accidentally - omitted. In the following, we always discuss the general toplevel form first and then cover the additional constraints placed on associated types.<br />
<br />
=== Family declarations ===<br />
<br />
Indexed data families are introduced by a signature, such as <br />
<haskell><br />
data family GMap k :: * -> *<br />
</haskell><br />
The special <hask>family</hask> distinguishes family from standard data declarations. The result kind annotation is optional and, as usual, defaults to <hask>*</hask> if omitted. An example is<br />
<haskell><br />
data family Array e<br />
</haskell><br />
Named arguments can also be given explicit kind signatures if needed. Just as with [http://www.haskell.org/ghc/docs/latest/html/users_guide/gadt.html GADT declarations] named arguments are entirely optional, so that we can declare <hask>Array</hask> alternatively with<br />
<haskell><br />
data family Array :: * -> *<br />
</haskell><br />
<br />
==== Associated family declarations ====<br />
<br />
When a data family is declared as part of a type class, we drop the <hask>family</hask> special. The <hask>GMap</hask> declaration takes the following form<br />
<haskell><br />
class GMapKey k where<br />
data GMap k :: * -> *<br />
...<br />
</haskell><br />
In contrast to toplevel declarations, named arguments must be used for all type parameters that are to be used as type-indexes. Moreover, the argument names must be class parameters. Each class parameter may only be used at most once per associated type, but some may be omitted and they may be in an order other than in the class head. Hence, the following contrieved example is admissible:<br />
<haskell><br />
class C a b c where<br />
data T c a :: *<br />
</haskell><br />
If kind signatures are required for argument variables, they need to be given in the class head.<br />
<br />
=== Instance declarations ===<br />
<br />
Instance declarations of data and newtype families are very similar to standard data and newtype declarations. The only two differences are that the keyword <hask>data</hask> or <hask>newtype</hask> is followed by <hask>instance</hask> and that some or all of the type arguments can be non-variable types. For example, the <hask>Either</hask> instance for <hask>GMap</hask> is<br />
<haskell><br />
data instance GMap (Either a b) v = GMapEither (GMap a v) (GMap b v)<br />
</haskell><br />
In this example, the declaration has only one variant. In general, it can be be any number.<br />
<br />
Data and newtype instance declarations are only legit when an appropriate family declaration is in scope - just like class instances require the class declaration to be visible. Moreover, each instance declaration has to conform to the kind determined by its family declaration. This implies that the number of parameters of an instance declaration matches the arity determined by the kind of the family. Although, all data families are declared with the <hask>data</hask> keyword, instances can be either <hask>data</hask> or <hask>newtype</hask>s, or a mix of both.<br />
<br />
Even if type families are defined as toplevel declarations, functions that perform different computations for different family instances still need to be defined as methods of type classes. In particular, the following is not possible:<br />
<haskell><br />
data family T a<br />
data instance T Int = A<br />
data instance T Char = B<br />
nonsence :: T a -> Int<br />
nonsence A = 1 -- WRONG: These two equations together...<br />
nonsence B = 2 -- ...will produce a type error.<br />
</haskell><br />
Given the functionality provided by GADTs (Generalised Algebraic Data Types), it might seem as if a definition, such as the above, should be feasible. However, type families are - in contrast to GADTs - are ''open''; i.e., new instances can always be added, possibly in other modules. Supporting pattern matching across different data instances would require a form of extensible case construct.<br />
<br />
==== Associated type instances ====<br />
<br />
When an associated family instance is declared within a type class instance, we drop the <hask>instance</hask> keyword in the family instance. So, the <hask>Either</hask> instance for <hask>GMap</hask> becomes:<br />
<haskell><br />
instance (GMapKey a, GMapKey b) => GMapKey (Either a b) where<br />
data GMap (Either a b) v = GMapEither (GMap a v) (GMap b v<br />
...<br />
</haskell><br />
The most important point about associated family instances is that the type indexes corresponding to class parameters must be identical to the type given in the instance head; here this is first argument of <hask>GMap</hask>, namely <hask>Either a b</hask>, which coincides with the only class parameter. Any parameters to the family constructor that do not correspond to class parameters, need to be variables in every instance; here this is the variable <hask>v</hask>.<br />
<br />
Instances for an associated family can only appear as part of instances declarations of the class in which the family was declared - just as with the equations of the methods of a class. Also in correspondence to how methods are handled, declarations of associated types can be omitted in class instances. If an associated family instance is omitted, the corresponding instance type is not inhabited; i.e., only diverging expressions, such as <hask>undefined</hask>, can assume the type.<br />
<br />
==== Class instances of type instances ====<br />
<br />
Type class instances of instances of data families can be defined as usual, and in particular data instance declarations can have <hask>deriving</hask> clauses. For example, we can write<br />
<haskell><br />
data GMap () v = GMapUnit (Maybe v)<br />
deriving Show<br />
</haskell><br />
which implcitly defines an instance of the form<br />
<haskell><br />
instance Show v => Show (GMap () v) where ...<br />
</haskell><br />
<br />
Note that class instances are always for particular ''instances'' of a data family and never for an entire family as a whole. This for essentially the same reasons that we cannot define a toplevel function that performs pattern matching on the data constructors of ''different'' instances of a single type family. It would require a form of extensible case construct.<br />
<br />
==== Overlap ====<br />
<br />
The instance declarations of a data family used in a single program may not overlap at all, independent of whether they are associated or not. In contrast to type class instances, this is not only a matter of consistency, but one of type safety.<br />
<br />
=== Import and export ===<br />
<br />
The association of data constructors with type families is more dynamic than that is the case with standard data and newtype declarations. In the standard case, the notation <hask>T(..)</hask> in an import or export list denotes the type constructor and all the data constructors introduced in its declaration. However, a family declaration never introduces any data constructors; instead, data constructors are introduced by family instances. As a result, which data constructors are associated with a type family depends on the currently visible instance declarations for that family. Consequently, an import or export item of the form <hask>T(..)</hask> denotes the family constructor and all currently visible data constructors - in the case of an export item, these may be either imported or defined in the current module. The treatment of import and export items that explicitly list data constructors, such as <hask>GMap(GMapEither)</hask>, is analogous.<br />
<br />
==== Associated families ====<br />
<br />
As expected, an import or export item of the form <hask>C(..)</hask> denotes all of the class' methods and associated types. However, when associated types are explicitly listed as subitems of a class, we need some new syntax, as uppercase identifiers as subitems are usually data constructors, not type constructors. To clarify that we denote types here, each associated type name needs to be prefixed by the keyword <hask>type</hask>. So for example, when explicitly listing the components of the <hask>GMapKey</hask> class, we write <hask>GMapKey(type GMap, empty, lookup, insert)</hask>.<br />
<br />
==== Examples ====<br />
<br />
Assuming our running <hask>GMapKey</hask> class example, let us look at some export lists and their meaning:<br />
<br />
* <hask>module GMap (GMapKey) where...</hask>: Exports just the class name.<br />
* <hask>module GMap (GMapKey(..)) where...</hask>: Exports the class, the associated type <hask>GMap</hask> and the member functions <hask>empty</hask>, <hask>lookup</hask>, and <hask>insert</hask>. None of the data constructors is exported.<br />
* <hask>module GMap (GMapKey(..), GMap(..)) where...</hask>: As before, but also exports all the data constructors <hask>GMapInt</hask>, <hask>GMapChar</hask>, <hask>GMapUnit</hask>, <hask>GMapPair</hask>, and <hask>GMapUnit</hask>.<br />
* <hask>module GMap (GMapKey(empty, lookup, insert), GMap(..)) where...</hask>: As before.<br />
* <hask>module GMap (GMapKey, empty, lookup, insert, GMap(..)) where...</hask>: As before.<br />
<br />
Finally, you can write <hask>GMapKey(type GMap)</hask> to denote both the class <hask>GMapKey</hask> as well as its associated type <hask>GMap</hask>. However, you cannot write <hask>GMapKey(type GMap(..))</hask> &mdash; i.e., sub-component specifications cannot be nested. To specify <hask>GMap</hask>'s data constructors, you have to list it separately.<br />
<br />
==== Instances ====<br />
<br />
Family instances are implicitly exported, just like class instances. However, this applies only to the heads of instances, not to the data constructors an instance defines.<br />
<br />
<br />
== A associated type synonym example ==<br />
<br />
Associated data types ar much better behaved than<br />
functional dependencies. Hence, GHC's type checking and inference are<br />
more powerful. Here is an example of how to port your existing functional <br />
depenency programs to associated type synonyms.<br />
<br />
=== The <hask>class</hask> declaration ===<br />
<br />
Here's an example from the original Functional Dependencies paper:<br />
<haskell><br />
class Collects e ce | ce -> e where<br />
empty :: ce<br />
insert :: e -> ce -> ce<br />
member :: e -> ce -> Bool<br />
toList :: ce -> [e]<br />
</haskell><br />
<br />
With associated type synonyms we can write this as:<br />
<haskell><br />
class Collects ce where<br />
type Elem ce<br />
empty :: ce<br />
insert :: Elem ce -> ce -> ce<br />
member :: Elem ce -> ce -> Bool<br />
toList :: ce -> [Elem ce]<br />
</haskell><br />
That's right, we have dropped from a multi-paramter type class<br />
to a single parameter type class. The parameter <hask>e</hask><br />
has become an associated type <hask>Elem ce</hask>.<br />
<br />
=== An <hask>instance</hask>===<br />
<br />
Here's an instance, with functional dependencies:<br />
<haskell><br />
instance Eq e => Collects e [e] where<br />
empty = []<br />
insert e l = (e:l)<br />
member e [] = False<br />
member e (x:xs) | e == x = True<br />
| otherwise = member e xs<br />
toList l = l<br />
</haskell><br />
<br />
With associated type synonyms, this becomes:<br />
<haskell><br />
instance Eq e => Collects [e] where<br />
type Elem [e] = e<br />
empty = []<br />
insert e l = (e:l)<br />
member e [] = False<br />
member e (x:xs) | e == x = True<br />
| otherwise = member e xs<br />
toList l = l<br />
</haskell><br />
<br />
=== Using generic collections ===<br />
<br />
With Functional Dependencies the code would be:<br />
<haskell><br />
sumCollects :: (Collects e c1,Collects e c2) => c1 -> c2 -> c2<br />
sumCollects c1 c2 = foldr insert c2 (toList c1)<br />
</haskell><br />
<br />
In contrast, with associated type synonyms, we get:<br />
<haskell><br />
sumCollects :: (Collects c1,Collects c2,Elem c1 ~ Elem c2) => c1 -> c2 -> c2<br />
sumCollects c1 c2 = foldr insert c2 (toList c1)<br />
</haskell><br />
<br />
<br />
== Definition of the type system extension ==<br />
<br />
['''NB:''' The following material will eventually become documentation for type families in the GHC User Manual. Please help to improve it by forwarding suggestions to <tt>tom.schrijvers@cs.kuleuven.be</tt>.]<br />
<br />
Type families appear in two flavours: (1) they can be defined on the toplevel or (2) they can appear inside type classes (in which case they are known as associated type synonyms). The former is the more general variant, as it lacks the requirement for the type-indexes to coincide with the class parameters. However, the later can lead to more clearly structured code and compiler warnings if some type instances were - possibly accidentally - omitted. In the following, we always discuss the general toplevel form first and then cover the additional constraints placed on associated types.<br />
<br />
=== Family declarations ===<br />
<br />
Indexed type families are introduced by a signature, such as <br />
<haskell><br />
type family Elem c :: *<br />
</haskell><br />
The special <hask>family</hask> distinguishes family from standard type declarations. The result kind annotation is optional and, as usual, defaults to <hask>*</hask> if omitted. An example is<br />
<haskell><br />
type family Elem c<br />
</haskell><br />
Named arguments can also be given explicit kind signatures if needed. Named arguments are _not_ optional.<br />
<br />
==== Associated family declarations ====<br />
<br />
When a type family is declared as part of a type class, we drop the <hask>family</hask> special. The <hask>Elem</hask> declaration takes the following form<br />
<haskell><br />
class Collects ce where<br />
type Elem ce :: *<br />
...<br />
</haskell><br />
The argument names of the type family must be class parameters. Each class parameter may only be used at most once per associated type, but some may be omitted and they may be in an order other than in the class head. Hence, the following contrieved example is admissible:<br />
<haskell><br />
class C a b c where<br />
type T c a :: *<br />
</haskell><br />
If kind signatures are required for argument variables, they need to be given in the class head.<br />
<br />
<br />
=== Instance declarations ===<br />
<br />
Instance declarations of type families are very similar to standard type synonym declarations. The only two differences are that the keyword <hask>type</hask> is followed by <hask>instance</hask> and that some or all of the type arguments can be non-variable types. For example, the <hask>[e]</hask> instance for <hask>Elem</hask> is<br />
<haskell><br />
type instance Elem [e] = e<br />
</haskell><br />
<br />
Type family instance declarations are only legitimate when an appropriate family declaration is in scope - just like class instances require the class declaration to be visible. Moreover, each instance declaration has to conform to the kind determined by its family declaration. This implies that the number of parameters of an instance declaration matches the arity determined by the kind of the family.<br />
<br />
Even if type families are defined as toplevel declarations, functions that perform different computations for different family instances still need to be defined as methods of type classes. In particular, the following is not possible:<br />
<haskell><br />
type family T a<br />
type instance T Int = A<br />
type instance T Char = B<br />
nonsence :: T a -> Int<br />
nonsence A = 1 -- WRONG: These two equations together...<br />
nonsence B = 2 -- ...will produce a type error.<br />
</haskell><br />
It might seem as if a definition, such as the above, should be feasible. However, type families are are ''open''; i.e., new instances can always be added, possibly in other modules. Supporting pattern matching across different type instances would require a form of extensible case construct.<br />
<br />
==== Associated type instances ====<br />
<br />
When an associated family instance is declared within a type class instance, we drop the <hask>instance</hask> keyword in the family instance. So, the <hask>[e]</hask> instance for <hask>Elem</hask> becomes:<br />
<haskell><br />
instance (Eq (Elem [e])) => Collects ([e]) where<br />
type Elem [e] = e<br />
...<br />
</haskell><br />
The most important point about associated family instances is that the type indexes corresponding to class parameters must be identical to the type given in the instance head; here this is <hask>[e]</hask>, which coincides with the only class parameter.<br />
<br />
Instances for an associated family can only appear as part of instances declarations of the class in which the family was declared - just as with the equations of the methods of a class. Also in correspondence to how methods are handled, declarations of associated types can be omitted in class instances. If an associated family instance is omitted, the corresponding instance type is not inhabited; i.e., only diverging expressions, such as <hask>undefined</hask>, can assume the type.<br />
<br />
==== Overlap ====<br />
<br />
The instance declarations of a type family used in a single program may not overlap at all, independent of whether they are associated or not. This is not only a matter of consistency, but one of type safety.<br />
<br />
<br />
== Open issues ==<br />
<br />
<br />
None.</div>Tschrijvershttps://wiki.haskell.org/index.php?title=GHC/Type_families&diff=13224GHC/Type families2007-05-25T13:41:21Z<p>Tschrijvers: </p>
<hr />
<div>[[Category:GHC|Indexed types]]<br />
== Data and type families in GHC ==<br />
<br />
Data and type families are a new addition to GHC's type extensions. They are currently an '''experimental''' feature and so their design may still change to some degree. The current implementation covers ''data families'' (including newtypes), which can either be on the toplevel or inside class declarations - the latter are also known as [http://www.cse.unsw.edu.au/~chak/papers/CKPM05.html associated data types]. <br />
<br />
'''NB:''' Please note that type families (and hence also associated type synonyms) are '''not''' fully implemented yet. Any attempt to use them will lead to strange error messages. For the moment, you can only use <hask>data</hask> families.<br />
<br />
== What do I need to use data families? ==<br />
<br />
Indexed type families are implemented in GHC's HEAD (from version 6.7), which you can obtain in binary form from the [http://www.haskell.org/ghc/dist/current/dist/ nightly snapshots] or in source form from the [http://hackage.haskell.org/trac/ghc/wiki/Building/GettingTheSources source repository]. To enable indexed type families in GHC 6.7, you need to supply the compiler option <tt>-ftype-families</tt> (or <tt>-fglasgow-exts</tt>, which implies it). NB: The option used to be called <tt>-findexed-types</tt> for a while.<br />
<br />
== An associated data type example ==<br />
<br />
As an example, consider Ralf Hinze's [http://www.informatik.uni-bonn.de/~ralf/publications.html#J4 generalised tries], a form of generic finite maps. <br />
<br />
=== The class declaration ===<br />
<br />
We define a type class whose instances are the types that we can use as keys in our generic maps:<br />
<haskell><br />
class GMapKey k where<br />
data GMap k :: * -> *<br />
empty :: GMap k v<br />
lookup :: k -> GMap k v -> Maybe v<br />
insert :: k -> v -> GMap k v -> GMap k v<br />
</haskell><br />
The interesting part is the ''associated data family'' declaration of the class. It gives a [http://www.haskell.org/ghc/docs/latest/html/users_guide/type-extensions.html#sec-kinding ''kind signature''] (here <hask>* -> *</hask>) for the associated data type <hask>GMap k</hask> - analog to how methods receive a type signature in a class declaration.<br />
<br />
What it is important to notice is that the first parameter of the associated type <hask>GMap</hask> coincides with the class parameter of <hask>GMapKey</hask>. This indicates that also in all instances of the class, the instances of the associated data type need to have their first argument match up with the instance type. In general, the type arguments of an associated type can be a subset of the class parameters (in a multi-parameter type class) and they can appear in any order, possibly in an order other than in the class head. The latter can be useful if the associated data type is partially applied in some contexts.<br />
<br />
The second important point is that as <hask>GMap k</hask> has kind <hask>* -> *</hask> and <hask>k</hask> (implicitly) has kind <hask>*</hask>, the type constructor <hask>GMap</hask> (without an argument) has kind <hask>* -> * -> *</hask>. Consequently, we see that <hask>GMap</hask> is applied to two arguments in the signatures of the methods <hask>empty</hask>, <hask>lookup</hask>, and <hask>insert</hask>.<br />
<br />
=== An Int instance ===<br />
<br />
To use Ints as keys into generic maps, we declare an instance that simply uses <hask>Data.Map</hask>, thusly:<br />
<haskell><br />
instance GMapKey Int where<br />
data GMap Int v = GMapInt (Data.Map.Map Int v)<br />
empty = GMapInt Data.Map.empty<br />
lookup k (GMapInt m) = Data.Map.lookup k m<br />
insert k v (GMapInt m) = GMapInt (Data.Map.insert k v m)<br />
</haskell><br />
The <hask>Int</hask> instance of the associated data type <hask>GMap</hask> needs to have both of its parameters, but as only the first one corresponds to a class parameter, the second needs to be a type variable (here <hask>v</hask>). As mentioned before any associated type parameter that corresponds to a class parameter must be identical to the class parameter in each instance. The right hand side of the associated data declaration is like that of any other data type.<br />
<br />
NB: At the moment, GADT syntax is not allowed for associated data types (or other indexed types). This is not a fundemental limitation, but just a shortcoming of the current implementation, which we expect to lift in the future.<br />
<br />
As an exercise, implement an instance for <hask>Char</hask> that maps back to the <hask>Int</hask> instance using the conversion functions <hask>Char.ord</hask> and <hask>Char.chr</hask>.<br />
<br />
=== A unit instance ===<br />
<br />
Generic definitions, apart from elementary types, typically cover units, products, and sums. We start here with the unit instance for <hask>GMap</hask>:<br />
<haskell><br />
instance GMapKey () where<br />
data GMap () v = GMapUnit (Maybe v)<br />
empty = GMapUnit Nothing<br />
lookup () (GMapUnit v) = v<br />
insert () v (GMapUnit _) = GMapUnit $ Just v<br />
</haskell><br />
For unit, the map is just a <hask>Maybe</hask> value.<br />
<br />
=== Product and sum instances ===<br />
<br />
Nest, let us define the instances for pairs and sums (i.e., <hask>Either</hask>):<br />
<haskell><br />
instance (GMapKey a, GMapKey b) => GMapKey (a, b) where<br />
data GMap (a, b) v = GMapPair (GMap a (GMap b v))<br />
empty = GMapPair empty<br />
lookup (a, b) (GMapPair gm) = lookup a gm >>= lookup b <br />
insert (a, b) v (GMapPair gm) = GMapPair $ case lookup a gm of<br />
Nothing -> insert a (insert b v empty) gm<br />
Just gm2 -> insert a (insert b v gm2 ) gm<br />
<br />
instance (GMapKey a, GMapKey b) => GMapKey (Either a b) where<br />
data GMap (Either a b) v = GMapEither (GMap a v) (GMap b v)<br />
empty = GMapEither empty empty<br />
lookup (Left a) (GMapEither gm1 _gm2) = lookup a gm1<br />
lookup (Right b) (GMapEither _gm1 gm2 ) = lookup b gm2<br />
insert (Left a) v (GMapEither gm1 gm2) = GMapEither (insert a v gm1) gm2<br />
insert (Right a) v (GMapEither gm1 gm2) = GMapEither gm1 (insert a v gm2)<br />
</haskell><br />
If you find this code algorithmically surprising, I'd suggest to have a look at [http://www.informatik.uni-bonn.de/~ralf/publications.html#J4 Ralf Hinze's paper]. The only novelty concerning associated types, in these two instances, is that the instances have a context <hask>(GMapKey a, GMapKey b)</hask>. Consequently, the right hand sides of the associated type declarations can use <hask>GMap</hask> recursively at the key types <hask>a</hask> and <hask>b</hask> - not unlike the method definitions use the class methods recursively at the types for which the class is given in the instance context.<br />
<br />
=== Using a generic map ===<br />
<br />
Finally, some code building and quering a generic map:<br />
<haskell><br />
myGMap :: GMap (Int, Either Char ()) String<br />
myGMap = insert (5, Left 'c') "(5, Left 'c')" $<br />
insert (4, Right ()) "(4, Right ())" $<br />
insert (5, Right ()) "This is the one!" $<br />
insert (5, Right ()) "This is the two!" $<br />
insert (6, Right ()) "(6, Right ())" $<br />
insert (5, Left 'a') "(5, Left 'a')" $<br />
empty<br />
main = putStrLn $ maybe "Couldn't find key!" id $ lookup (5, Right ()) myGMap<br />
</haskell><br />
<br />
=== Download the code ===<br />
<br />
If you want to play with this example without copying it off the wiki, just download the [http://darcs.haskell.org/testsuite/tests/ghc-regress/indexed-types/should_run/GMapAssoc.hs source code for <hask>GMap</hask>] from GHC's test suite.<br />
<br />
== Definition of the type system extension ==<br />
<br />
['''NB:''' The following material will eventually become documentation for type families in the GHC User Manual. Please help to improve it by forwarding suggestions to <tt>chak@cse.unsw.edu.au</tt>.]<br />
<br />
Data families appear in two flavours: (1) they can be defined on the toplevel or (2) they can appear inside type classes (in which case they are known as associated types). The former is the more general variant, as it lacks the requirement for the type-indexes to coincide with the class parameters. However, the later can lead to more clearly structured code and compiler warnings if some type instances were - possibly accidentally - omitted. In the following, we always discuss the general toplevel form first and then cover the additional constraints placed on associated types.<br />
<br />
=== Family declarations ===<br />
<br />
Indexed data families are introduced by a signature, such as <br />
<haskell><br />
data family GMap k :: * -> *<br />
</haskell><br />
The special <hask>family</hask> distinguishes family from standard data declarations. The result kind annotation is optional and, as usual, defaults to <hask>*</hask> if omitted. An example is<br />
<haskell><br />
data family Array e<br />
</haskell><br />
Named arguments can also be given explicit kind signatures if needed. Just as with [http://www.haskell.org/ghc/docs/latest/html/users_guide/gadt.html GADT declarations] named arguments are entirely optional, so that we can declare <hask>Array</hask> alternatively with<br />
<haskell><br />
data family Array :: * -> *<br />
</haskell><br />
<br />
==== Associated family declarations ====<br />
<br />
When a data family is declared as part of a type class, we drop the <hask>family</hask> special. The <hask>GMap</hask> declaration takes the following form<br />
<haskell><br />
class GMapKey k where<br />
data GMap k :: * -> *<br />
...<br />
</haskell><br />
In contrast to toplevel declarations, named arguments must be used for all type parameters that are to be used as type-indexes. Moreover, the argument names must be class parameters. Each class parameter may only be used at most once per associated type, but some may be omitted and they may be in an order other than in the class head. Hence, the following contrieved example is admissible:<br />
<haskell><br />
class C a b c where<br />
data T c a :: *<br />
</haskell><br />
If kind signatures are required for argument variables, they need to be given in the class head.<br />
<br />
=== Instance declarations ===<br />
<br />
Instance declarations of data and newtype families are very similar to standard data and newtype declarations. The only two differences are that the keyword <hask>data</hask> or <hask>newtype</hask> is followed by <hask>instance</hask> and that some or all of the type arguments can be non-variable types. For example, the <hask>Either</hask> instance for <hask>GMap</hask> is<br />
<haskell><br />
data instance GMap (Either a b) v = GMapEither (GMap a v) (GMap b v)<br />
</haskell><br />
In this example, the declaration has only one variant. In general, it can be be any number.<br />
<br />
Data and newtype instance declarations are only legit when an appropriate family declaration is in scope - just like class instances require the class declaration to be visible. Moreover, each instance declaration has to conform to the kind determined by its family declaration. This implies that the number of parameters of an instance declaration matches the arity determined by the kind of the family. Although, all data families are declared with the <hask>data</hask> keyword, instances can be either <hask>data</hask> or <hask>newtype</hask>s, or a mix of both.<br />
<br />
Even if type families are defined as toplevel declarations, functions that perform different computations for different family instances still need to be defined as methods of type classes. In particular, the following is not possible:<br />
<haskell><br />
data family T a<br />
data instance T Int = A<br />
data instance T Char = B<br />
nonsence :: T a -> Int<br />
nonsence A = 1 -- WRONG: These two equations together...<br />
nonsence B = 2 -- ...will produce a type error.<br />
</haskell><br />
Given the functionality provided by GADTs (Generalised Algebraic Data Types), it might seem as if a definition, such as the above, should be feasible. However, type families are - in contrast to GADTs - are ''open''; i.e., new instances can always be added, possibly in other modules. Supporting pattern matching across different data instances would require a form of extensible case construct.<br />
<br />
==== Associated type instances ====<br />
<br />
When an associated family instance is declared within a type class instance, we drop the <hask>instance</hask> keyword in the family instance. So, the <hask>Either</hask> instance for <hask>GMap</hask> becomes:<br />
<haskell><br />
instance (GMapKey a, GMapKey b) => GMapKey (Either a b) where<br />
data GMap (Either a b) v = GMapEither (GMap a v) (GMap b v<br />
...<br />
</haskell><br />
The most important point about associated family instances is that the type indexes corresponding to class parameters must be identical to the type given in the instance head; here this is first argument of <hask>GMap</hask>, namely <hask>Either a b</hask>, which coincides with the only class parameter. Any parameters to the family constructor that do not correspond to class parameters, need to be variables in every instance; here this is the variable <hask>v</hask>.<br />
<br />
Instances for an associated family can only appear as part of instances declarations of the class in which the family was declared - just as with the equations of the methods of a class. Also in correspondence to how methods are handled, declarations of associated types can be omitted in class instances. If an associated family instance is omitted, the corresponding instance type is not inhabited; i.e., only diverging expressions, such as <hask>undefined</hask>, can assume the type.<br />
<br />
==== Class instances of type instances ====<br />
<br />
Type class instances of instances of data families can be defined as usual, and in particular data instance declarations can have <hask>deriving</hask> clauses. For example, we can write<br />
<haskell><br />
data GMap () v = GMapUnit (Maybe v)<br />
deriving Show<br />
</haskell><br />
which implcitly defines an instance of the form<br />
<haskell><br />
instance Show v => Show (GMap () v) where ...<br />
</haskell><br />
<br />
Note that class instances are always for particular ''instances'' of a data family and never for an entire family as a whole. This for essentially the same reasons that we cannot define a toplevel function that performs pattern matching on the data constructors of ''different'' instances of a single type family. It would require a form of extensible case construct.<br />
<br />
==== Overlap ====<br />
<br />
The instance declarations of a data family used in a single program may not overlap at all, independent of whether they are associated or not. In contrast to type class instances, this is not only a matter of consistency, but one of type safety.<br />
<br />
=== Import and export ===<br />
<br />
The association of data constructors with type families is more dynamic than that is the case with standard data and newtype declarations. In the standard case, the notation <hask>T(..)</hask> in an import or export list denotes the type constructor and all the data constructors introduced in its declaration. However, a family declaration never introduces any data constructors; instead, data constructors are introduced by family instances. As a result, which data constructors are associated with a type family depends on the currently visible instance declarations for that family. Consequently, an import or export item of the form <hask>T(..)</hask> denotes the family constructor and all currently visible data constructors - in the case of an export item, these may be either imported or defined in the current module. The treatment of import and export items that explicitly list data constructors, such as <hask>GMap(GMapEither)</hask>, is analogous.<br />
<br />
==== Associated families ====<br />
<br />
As expected, an import or export item of the form <hask>C(..)</hask> denotes all of the class' methods and associated types. However, when associated types are explicitly listed as subitems of a class, we need some new syntax, as uppercase identifiers as subitems are usually data constructors, not type constructors. To clarify that we denote types here, each associated type name needs to be prefixed by the keyword <hask>type</hask>. So for example, when explicitly listing the components of the <hask>GMapKey</hask> class, we write <hask>GMapKey(type GMap, empty, lookup, insert)</hask>.<br />
<br />
==== Examples ====<br />
<br />
Assuming our running <hask>GMapKey</hask> class example, let us look at some export lists and their meaning:<br />
<br />
* <hask>module GMap (GMapKey) where...</hask>: Exports just the class name.<br />
* <hask>module GMap (GMapKey(..)) where...</hask>: Exports the class, the associated type <hask>GMap</hask> and the member functions <hask>empty</hask>, <hask>lookup</hask>, and <hask>insert</hask>. None of the data constructors is exported.<br />
* <hask>module GMap (GMapKey(..), GMap(..)) where...</hask>: As before, but also exports all the data constructors <hask>GMapInt</hask>, <hask>GMapChar</hask>, <hask>GMapUnit</hask>, <hask>GMapPair</hask>, and <hask>GMapUnit</hask>.<br />
* <hask>module GMap (GMapKey(empty, lookup, insert), GMap(..)) where...</hask>: As before.<br />
* <hask>module GMap (GMapKey, empty, lookup, insert, GMap(..)) where...</hask>: As before.<br />
<br />
Finally, you can write <hask>GMapKey(type GMap)</hask> to denote both the class <hask>GMapKey</hask> as well as its associated type <hask>GMap</hask>. However, you cannot write <hask>GMapKey(type GMap(..))</hask> &mdash; i.e., sub-component specifications cannot be nested. To specify <hask>GMap</hask>'s data constructors, you have to list it separately.<br />
<br />
==== Instances ====<br />
<br />
Family instances are implicitly exported, just like class instances. However, this applies only to the heads of instances, not to the data constructors an instance defines.<br />
<br />
<br />
== A associated type synonym example ==<br />
<br />
Associated data types ar much better behaved than<br />
functional dependencies. Hence, GHC's type checking and inference are<br />
more powerful. Here is an example of how to port your existing functional <br />
depenency programs to associated type synonyms.<br />
<br />
=== The <hask>class</hask> declaration ===<br />
<br />
Here's an example from the original Functional Dependencies paper:<br />
<haskell><br />
class Collects e ce | ce -> e where<br />
empty :: ce<br />
insert :: e -> ce -> ce<br />
member :: e -> ce -> Bool<br />
toList :: ce -> [e]<br />
</haskell><br />
<br />
With associated type synonyms we can write this as:<br />
<haskell><br />
class Collects ce where<br />
type Elem ce<br />
empty :: ce<br />
insert :: Elem ce -> ce -> ce<br />
member :: Elem ce -> ce -> Bool<br />
toList :: ce -> [Elem ce]<br />
</haskell><br />
That's right, we have dropped from a multi-paramter type class<br />
to a single parameter type class. The parameter <hask>e</hask><br />
has become an associated type <hask>Elem ce</hask>.<br />
<br />
=== An <hask>instance</hask>===<br />
<br />
Here's an instance, with functional dependencies:<br />
<haskell><br />
instance Eq e => Collects e [e] where<br />
empty = []<br />
insert e l = (e:l)<br />
member e [] = False<br />
member e (x:xs) | e == x = True<br />
| otherwise = member e xs<br />
toList l = l<br />
</haskell><br />
<br />
With associated type synonyms, this becomes:<br />
<haskell><br />
instance Eq e => Collects [e] where<br />
type Elem [e] = e<br />
empty = []<br />
insert e l = (e:l)<br />
member e [] = False<br />
member e (x:xs) | e == x = True<br />
| otherwise = member e xs<br />
toList l = l<br />
</haskell><br />
<br />
=== Using generic collections ===<br />
<br />
With Functional Dependencies the code would be:<br />
<haskell><br />
sumCollects :: (Collects e c1,Collects e c2) => c1 -> c2 -> c2<br />
sumCollects c1 c2 = foldr insert c2 (toList c1)<br />
</haskell><br />
<br />
In contrast, with associated type synonyms, we get:<br />
<haskell><br />
sumCollects :: (Collects c1,Collects c2,Elem c1 ~ Elem c2) => c1 -> c2 -> c2<br />
sumCollects c1 c2 = foldr insert c2 (toList c1)<br />
</haskell><br />
<br />
<br />
== Definition of the type system extension ==<br />
<br />
['''NB:''' The following material will eventually become documentation for type families in the GHC User Manual. Please help to improve it by forwarding suggestions to <tt>tom.schrijvers@cs.kuleuven.be</tt>.]<br />
<br />
Type families appear in two flavours: (1) they can be defined on the toplevel or (2) they can appear inside type classes (in which case they are known as associated type synonyms). The former is the more general variant, as it lacks the requirement for the type-indexes to coincide with the class parameters. However, the later can lead to more clearly structured code and compiler warnings if some type instances were - possibly accidentally - omitted. In the following, we always discuss the general toplevel form first and then cover the additional constraints placed on associated types.<br />
<br />
=== Family declarations ===<br />
<br />
Indexed type families are introduced by a signature, such as <br />
<haskell><br />
type family Elem c :: *<br />
</haskell><br />
The special <hask>family</hask> distinguishes family from standard type declarations. The result kind annotation is optional and, as usual, defaults to <hask>*</hask> if omitted. An example is<br />
<haskell><br />
type family Elem c<br />
</haskell><br />
Named arguments can also be given explicit kind signatures if needed. Named arguments are _not_ optional.<br />
<br />
==== Associated family declarations ====<br />
<br />
When a type family is declared as part of a type class, we drop the <hask>family</hask> special. The <hask>Elem</hask> declaration takes the following form<br />
<haskell><br />
class Collects ce where<br />
type Elem ce :: *<br />
...<br />
</haskell><br />
The argument names of the type family must be class parameters. Each class parameter may only be used at most once per associated type, but some may be omitted and they may be in an order other than in the class head. Hence, the following contrieved example is admissible:<br />
<haskell><br />
class C a b c where<br />
type T c a :: *<br />
</haskell><br />
If kind signatures are required for argument variables, they need to be given in the class head.<br />
<br />
<br />
=== Instance declarations ===<br />
<br />
Instance declarations of type families are very similar to standard type synonym declarations. The only two differences are that the keyword <hask>type</hask> is followed by <hask>instance</hask> and that some or all of the type arguments can be non-variable types. For example, the <hask>[e]</hask> instance for <hask>Elem</hask> is<br />
<haskell><br />
type instance Elem [e] = e<br />
</haskell><br />
<br />
Type family instance declarations are only legitimate when an appropriate family declaration is in scope - just like class instances require the class declaration to be visible. Moreover, each instance declaration has to conform to the kind determined by its family declaration. This implies that the number of parameters of an instance declaration matches the arity determined by the kind of the family.<br />
<br />
Even if type families are defined as toplevel declarations, functions that perform different computations for different family instances still need to be defined as methods of type classes. In particular, the following is not possible:<br />
<haskell><br />
type family T a<br />
type instance T Int = A<br />
type instance T Char = B<br />
nonsence :: T a -> Int<br />
nonsence A = 1 -- WRONG: These two equations together...<br />
nonsence B = 2 -- ...will produce a type error.<br />
</haskell><br />
It might seem as if a definition, such as the above, should be feasible. However, type families are are ''open''; i.e., new instances can always be added, possibly in other modules. Supporting pattern matching across different type instances would require a form of extensible case construct.<br />
<br />
==== Associated type instances ====<br />
<br />
When an associated family instance is declared within a type class instance, we drop the <hask>instance</hask> keyword in the family instance. So, the <hask>[e]</hask> instance for <hask>Elem</hask> becomes:<br />
<haskell><br />
instance (Eq (Elem [e])) => Collects ([e]) where<br />
type Elem [e] = e<br />
...<br />
</haskell><br />
The most important point about associated family instances is that the type indexes corresponding to class parameters must be identical to the type given in the instance head; here this is <hask>[e]</hask>, which coincides with the only class parameter.<br />
<br />
Instances for an associated family can only appear as part of instances declarations of the class in which the family was declared - just as with the equations of the methods of a class. Also in correspondence to how methods are handled, declarations of associated types can be omitted in class instances. If an associated family instance is omitted, the corresponding instance type is not inhabited; i.e., only diverging expressions, such as <hask>undefined</hask>, can assume the type.<br />
<br />
<br />
== Open issues ==<br />
<br />
<br />
None.</div>Tschrijvershttps://wiki.haskell.org/index.php?title=GHC/Type_families&diff=13221GHC/Type families2007-05-25T10:39:40Z<p>Tschrijvers: </p>
<hr />
<div>[[Category:GHC|Indexed types]]<br />
== Data and type families in GHC ==<br />
<br />
Data and type families are a new addition to GHC's type extensions. They are currently an '''experimental''' feature and so their design may still change to some degree. The current implementation covers ''data families'' (including newtypes), which can either be on the toplevel or inside class declarations - the latter are also known as [http://www.cse.unsw.edu.au/~chak/papers/CKPM05.html associated data types]. <br />
<br />
'''NB:''' Please note that type families (and hence also associated type synonyms) are '''not''' fully implemented yet. Any attempt to use them will lead to strange error messages. For the moment, you can only use <hask>data</hask> families.<br />
<br />
== What do I need to use data families? ==<br />
<br />
Indexed type families are implemented in GHC's HEAD (from version 6.7), which you can obtain in binary form from the [http://www.haskell.org/ghc/dist/current/dist/ nightly snapshots] or in source form from the [http://hackage.haskell.org/trac/ghc/wiki/Building/GettingTheSources source repository]. To enable indexed type families in GHC 6.7, you need to supply the compiler option <tt>-ftype-families</tt> (or <tt>-fglasgow-exts</tt>, which implies it). NB: The option used to be called <tt>-findexed-types</tt> for a while.<br />
<br />
== An associated data type example ==<br />
<br />
As an example, consider Ralf Hinze's [http://www.informatik.uni-bonn.de/~ralf/publications.html#J4 generalised tries], a form of generic finite maps. <br />
<br />
=== The class declaration ===<br />
<br />
We define a type class whose instances are the types that we can use as keys in our generic maps:<br />
<haskell><br />
class GMapKey k where<br />
data GMap k :: * -> *<br />
empty :: GMap k v<br />
lookup :: k -> GMap k v -> Maybe v<br />
insert :: k -> v -> GMap k v -> GMap k v<br />
</haskell><br />
The interesting part is the ''associated data family'' declaration of the class. It gives a [http://www.haskell.org/ghc/docs/latest/html/users_guide/type-extensions.html#sec-kinding ''kind signature''] (here <hask>* -> *</hask>) for the associated data type <hask>GMap k</hask> - analog to how methods receive a type signature in a class declaration.<br />
<br />
What it is important to notice is that the first parameter of the associated type <hask>GMap</hask> coincides with the class parameter of <hask>GMapKey</hask>. This indicates that also in all instances of the class, the instances of the associated data type need to have their first argument match up with the instance type. In general, the type arguments of an associated type can be a subset of the class parameters (in a multi-parameter type class) and they can appear in any order, possibly in an order other than in the class head. The latter can be useful if the associated data type is partially applied in some contexts.<br />
<br />
The second important point is that as <hask>GMap k</hask> has kind <hask>* -> *</hask> and <hask>k</hask> (implicitly) has kind <hask>*</hask>, the type constructor <hask>GMap</hask> (without an argument) has kind <hask>* -> * -> *</hask>. Consequently, we see that <hask>GMap</hask> is applied to two arguments in the signatures of the methods <hask>empty</hask>, <hask>lookup</hask>, and <hask>insert</hask>.<br />
<br />
=== An Int instance ===<br />
<br />
To use Ints as keys into generic maps, we declare an instance that simply uses <hask>Data.Map</hask>, thusly:<br />
<haskell><br />
instance GMapKey Int where<br />
data GMap Int v = GMapInt (Data.Map.Map Int v)<br />
empty = GMapInt Data.Map.empty<br />
lookup k (GMapInt m) = Data.Map.lookup k m<br />
insert k v (GMapInt m) = GMapInt (Data.Map.insert k v m)<br />
</haskell><br />
The <hask>Int</hask> instance of the associated data type <hask>GMap</hask> needs to have both of its parameters, but as only the first one corresponds to a class parameter, the second needs to be a type variable (here <hask>v</hask>). As mentioned before any associated type parameter that corresponds to a class parameter must be identical to the class parameter in each instance. The right hand side of the associated data declaration is like that of any other data type.<br />
<br />
NB: At the moment, GADT syntax is not allowed for associated data types (or other indexed types). This is not a fundemental limitation, but just a shortcoming of the current implementation, which we expect to lift in the future.<br />
<br />
As an exercise, implement an instance for <hask>Char</hask> that maps back to the <hask>Int</hask> instance using the conversion functions <hask>Char.ord</hask> and <hask>Char.chr</hask>.<br />
<br />
=== A unit instance ===<br />
<br />
Generic definitions, apart from elementary types, typically cover units, products, and sums. We start here with the unit instance for <hask>GMap</hask>:<br />
<haskell><br />
instance GMapKey () where<br />
data GMap () v = GMapUnit (Maybe v)<br />
empty = GMapUnit Nothing<br />
lookup () (GMapUnit v) = v<br />
insert () v (GMapUnit _) = GMapUnit $ Just v<br />
</haskell><br />
For unit, the map is just a <hask>Maybe</hask> value.<br />
<br />
=== Product and sum instances ===<br />
<br />
Nest, let us define the instances for pairs and sums (i.e., <hask>Either</hask>):<br />
<haskell><br />
instance (GMapKey a, GMapKey b) => GMapKey (a, b) where<br />
data GMap (a, b) v = GMapPair (GMap a (GMap b v))<br />
empty = GMapPair empty<br />
lookup (a, b) (GMapPair gm) = lookup a gm >>= lookup b <br />
insert (a, b) v (GMapPair gm) = GMapPair $ case lookup a gm of<br />
Nothing -> insert a (insert b v empty) gm<br />
Just gm2 -> insert a (insert b v gm2 ) gm<br />
<br />
instance (GMapKey a, GMapKey b) => GMapKey (Either a b) where<br />
data GMap (Either a b) v = GMapEither (GMap a v) (GMap b v)<br />
empty = GMapEither empty empty<br />
lookup (Left a) (GMapEither gm1 _gm2) = lookup a gm1<br />
lookup (Right b) (GMapEither _gm1 gm2 ) = lookup b gm2<br />
insert (Left a) v (GMapEither gm1 gm2) = GMapEither (insert a v gm1) gm2<br />
insert (Right a) v (GMapEither gm1 gm2) = GMapEither gm1 (insert a v gm2)<br />
</haskell><br />
If you find this code algorithmically surprising, I'd suggest to have a look at [http://www.informatik.uni-bonn.de/~ralf/publications.html#J4 Ralf Hinze's paper]. The only novelty concerning associated types, in these two instances, is that the instances have a context <hask>(GMapKey a, GMapKey b)</hask>. Consequently, the right hand sides of the associated type declarations can use <hask>GMap</hask> recursively at the key types <hask>a</hask> and <hask>b</hask> - not unlike the method definitions use the class methods recursively at the types for which the class is given in the instance context.<br />
<br />
=== Using a generic map ===<br />
<br />
Finally, some code building and quering a generic map:<br />
<haskell><br />
myGMap :: GMap (Int, Either Char ()) String<br />
myGMap = insert (5, Left 'c') "(5, Left 'c')" $<br />
insert (4, Right ()) "(4, Right ())" $<br />
insert (5, Right ()) "This is the one!" $<br />
insert (5, Right ()) "This is the two!" $<br />
insert (6, Right ()) "(6, Right ())" $<br />
insert (5, Left 'a') "(5, Left 'a')" $<br />
empty<br />
main = putStrLn $ maybe "Couldn't find key!" id $ lookup (5, Right ()) myGMap<br />
</haskell><br />
<br />
=== Download the code ===<br />
<br />
If you want to play with this example without copying it off the wiki, just download the [http://darcs.haskell.org/testsuite/tests/ghc-regress/indexed-types/should_run/GMapAssoc.hs source code for <hask>GMap</hask>] from GHC's test suite.<br />
<br />
== Definition of the type system extension ==<br />
<br />
['''NB:''' The following material will eventually become documentation for type families in the GHC User Manual. Please help to improve it by forwarding suggestions to <tt>chak@cse.unsw.edu.au</tt>.]<br />
<br />
Data families appear in two flavours: (1) they can be defined on the toplevel or (2) they can appear inside type classes (in which case they are known as associated types). The former is the more general variant, as it lacks the requirement for the type-indexes to coincide with the class parameters. However, the later can lead to more clearly structured code and compiler warnings if some type instances were - possibly accidentally - omitted. In the following, we always discuss the general toplevel form first and then cover the additional constraints placed on associated types.<br />
<br />
=== Family declarations ===<br />
<br />
Indexed data families are introduced by a signature, such as <br />
<haskell><br />
data family GMap k :: * -> *<br />
</haskell><br />
The special <hask>family</hask> distinguishes family from standard data declarations. The result kind annotation is optional and, as usual, defaults to <hask>*</hask> if omitted. An example is<br />
<haskell><br />
data family Array e<br />
</haskell><br />
Named arguments can also be given explicit kind signatures if needed. Just as with [http://www.haskell.org/ghc/docs/latest/html/users_guide/gadt.html GADT declarations] named arguments are entirely optional, so that we can declare <hask>Array</hask> alternatively with<br />
<haskell><br />
data family Array :: * -> *<br />
</haskell><br />
<br />
==== Associated family declarations ====<br />
<br />
When a data family is declared as part of a type class, we drop the <hask>family</hask> special. The <hask>GMap</hask> declaration takes the following form<br />
<haskell><br />
class GMapKey k where<br />
data GMap k :: * -> *<br />
...<br />
</haskell><br />
In contrast to toplevel declarations, named arguments must be used for all type parameters that are to be used as type-indexes. Moreover, the argument names must be class parameters. Each class parameter may only be used at most once per associated type, but some may be omitted and they may be in an order other than in the class head. Hence, the following contrieved example is admissible:<br />
<haskell><br />
class C a b c where<br />
data T c a :: *<br />
</haskell><br />
If kind signatures are required for argument variables, they need to be given in the class head.<br />
<br />
=== Instance declarations ===<br />
<br />
Instance declarations of data and newtype families are very similar to standard data and newtype declarations. The only two differences are that the keyword <hask>data</hask> or <hask>newtype</hask> is followed by <hask>instance</hask> and that some or all of the type arguments can be non-variable types. For example, the <hask>Either</hask> instance for <hask>GMap</hask> is<br />
<haskell><br />
data instance GMap (Either a b) v = GMapEither (GMap a v) (GMap b v)<br />
</haskell><br />
In this example, the declaration has only one variant. In general, it can be be any number.<br />
<br />
Data and newtype instance declarations are only legit when an appropriate family declaration is in scope - just like class instances require the class declaration to be visible. Moreover, each instance declaration has to conform to the kind determined by its family declaration. This implies that the number of parameters of an instance declaration matches the arity determined by the kind of the family. Although, all data families are declared with the <hask>data</hask> keyword, instances can be either <hask>data</hask> or <hask>newtype</hask>s, or a mix of both.<br />
<br />
Even if type families are defined as toplevel declarations, functions that perform different computations for different family instances still need to be defined as methods of type classes. In particular, the following is not possible:<br />
<haskell><br />
data family T a<br />
data instance T Int = A<br />
data instance T Char = B<br />
nonsence :: T a -> Int<br />
nonsence A = 1 -- WRONG: These two equations together...<br />
nonsence B = 2 -- ...will produce a type error.<br />
</haskell><br />
Given the functionality provided by GADTs (Generalised Algebraic Data Types), it might seem as if a definition, such as the above, should be feasible. However, type families are - in contrast to GADTs - are ''open''; i.e., new instances can always be added, possibly in other modules. Supporting pattern matching across different data instances would require a form of extensible case construct.<br />
<br />
==== Associated type instances ====<br />
<br />
When an associated family instance is declared within a type class instance, we drop the <hask>instance</hask> keyword in the family instance. So, the <hask>Either</hask> instance for <hask>GMap</hask> becomes:<br />
<haskell><br />
instance (GMapKey a, GMapKey b) => GMapKey (Either a b) where<br />
data GMap (Either a b) v = GMapEither (GMap a v) (GMap b v<br />
...<br />
</haskell><br />
The most important point about associated family instances is that the type indexes corresponding to class parameters must be identical to the type given in the instance head; here this is first argument of <hask>GMap</hask>, namely <hask>Either a b</hask>, which coincides with the only class parameter. Any parameters to the family constructor that do not correspond to class parameters, need to be variables in every instance; here this is the variable <hask>v</hask>.<br />
<br />
Instances for an associated family can only appear as part of instances declarations of the class in which the family was declared - just as with the equations of the methods of a class. Also in correspondence to how methods are handled, declarations of associated types can be omitted in class instances. If an associated family instance is omitted, the corresponding instance type is not inhabited; i.e., only diverging expressions, such as <hask>undefined</hask>, can assume the type.<br />
<br />
==== Class instances of type instances ====<br />
<br />
Type class instances of instances of data families can be defined as usual, and in particular data instance declarations can have <hask>deriving</hask> clauses. For example, we can write<br />
<haskell><br />
data GMap () v = GMapUnit (Maybe v)<br />
deriving Show<br />
</haskell><br />
which implcitly defines an instance of the form<br />
<haskell><br />
instance Show v => Show (GMap () v) where ...<br />
</haskell><br />
<br />
Note that class instances are always for particular ''instances'' of a data family and never for an entire family as a whole. This for essentially the same reasons that we cannot define a toplevel function that performs pattern matching on the data constructors of ''different'' instances of a single type family. It would require a form of extensible case construct.<br />
<br />
==== Overlap ====<br />
<br />
The instance declarations of a data family used in a single program may not overlap at all, independent of whether they are associated or not. In contrast to type class instances, this is not only a matter of consistency, but one of type safety.<br />
<br />
=== Import and export ===<br />
<br />
The association of data constructors with type families is more dynamic than that is the case with standard data and newtype declarations. In the standard case, the notation <hask>T(..)</hask> in an import or export list denotes the type constructor and all the data constructors introduced in its declaration. However, a family declaration never introduces any data constructors; instead, data constructors are introduced by family instances. As a result, which data constructors are associated with a type family depends on the currently visible instance declarations for that family. Consequently, an import or export item of the form <hask>T(..)</hask> denotes the family constructor and all currently visible data constructors - in the case of an export item, these may be either imported or defined in the current module. The treatment of import and export items that explicitly list data constructors, such as <hask>GMap(GMapEither)</hask>, is analogous.<br />
<br />
==== Associated families ====<br />
<br />
As expected, an import or export item of the form <hask>C(..)</hask> denotes all of the class' methods and associated types. However, when associated types are explicitly listed as subitems of a class, we need some new syntax, as uppercase identifiers as subitems are usually data constructors, not type constructors. To clarify that we denote types here, each associated type name needs to be prefixed by the keyword <hask>type</hask>. So for example, when explicitly listing the components of the <hask>GMapKey</hask> class, we write <hask>GMapKey(type GMap, empty, lookup, insert)</hask>.<br />
<br />
==== Examples ====<br />
<br />
Assuming our running <hask>GMapKey</hask> class example, let us look at some export lists and their meaning:<br />
<br />
* <hask>module GMap (GMapKey) where...</hask>: Exports just the class name.<br />
* <hask>module GMap (GMapKey(..)) where...</hask>: Exports the class, the associated type <hask>GMap</hask> and the member functions <hask>empty</hask>, <hask>lookup</hask>, and <hask>insert</hask>. None of the data constructors is exported.<br />
* <hask>module GMap (GMapKey(..), GMap(..)) where...</hask>: As before, but also exports all the data constructors <hask>GMapInt</hask>, <hask>GMapChar</hask>, <hask>GMapUnit</hask>, <hask>GMapPair</hask>, and <hask>GMapUnit</hask>.<br />
* <hask>module GMap (GMapKey(empty, lookup, insert), GMap(..)) where...</hask>: As before.<br />
* <hask>module GMap (GMapKey, empty, lookup, insert, GMap(..)) where...</hask>: As before.<br />
<br />
Finally, you can write <hask>GMapKey(type GMap)</hask> to denote both the class <hask>GMapKey</hask> as well as its associated type <hask>GMap</hask>. However, you cannot write <hask>GMapKey(type GMap(..))</hask> &mdash; i.e., sub-component specifications cannot be nested. To specify <hask>GMap</hask>'s data constructors, you have to list it separately.<br />
<br />
==== Instances ====<br />
<br />
Family instances are implicitly exported, just like class instances. However, this applies only to the heads of instances, not to the data constructors an instance defines.<br />
<br />
<br />
== A associated type synonym example ==<br />
<br />
Associated data types ar much better behaved than<br />
functional dependencies. Hence, GHC's type checking and inference are<br />
more powerful. Here is an example of how to port your existing functional <br />
depenency programs to associated type synonyms.<br />
<br />
=== The <hask>class</hask> declaration ===<br />
<br />
Here's an example from the original Functional Dependencies paper:<br />
<haskell><br />
class Collects e ce | ce -> e where<br />
empty :: ce<br />
insert :: e -> ce -> ce<br />
member :: e -> ce -> Bool<br />
toList :: ce -> [e]<br />
</haskell><br />
<br />
With associated type synonyms we can write this as:<br />
<haskell><br />
class Collects ce where<br />
type Elem ce<br />
empty :: ce<br />
insert :: Elem ce -> ce -> ce<br />
member :: Elem ce -> ce -> Bool<br />
toList :: ce -> [Elem ce]<br />
</haskell><br />
That's right, we have dropped from a multi-paramter type class<br />
to a single parameter type class. The parameter <hask>e</hask><br />
has become an associated type <hask>Elem ce</hask>.<br />
<br />
=== An <hask>instance</hask>===<br />
<br />
Here's an instance, with functional dependencies:<br />
<haskell><br />
instance Eq e => Collects e [e] where<br />
empty = []<br />
insert e l = (e:l)<br />
member e [] = False<br />
member e (x:xs) | e == x = True<br />
| otherwise = member e xs<br />
toList l = l<br />
</haskell><br />
<br />
With associated type synonyms, this becomes:<br />
<haskell><br />
instance Eq e => Collects [e] where<br />
type Elem [e] = e<br />
empty = []<br />
insert e l = (e:l)<br />
member e [] = False<br />
member e (x:xs) | e == x = True<br />
| otherwise = member e xs<br />
toList l = l<br />
</haskell><br />
<br />
=== Using generic collections ===<br />
<br />
With Functional Dependencies the code would be:<br />
<haskell><br />
sumCollects :: (Collects e c1,Collects e c2) => c1 -> c2 -> c2<br />
sumCollects c1 c2 = foldr insert c2 (toList c1)<br />
</haskell><br />
<br />
In contrast, with associated type synonyms, we get:<br />
<haskell><br />
sumCollects :: (Collects c1,Collects c2,Elem c1 ~ Elem c2) => c1 -> c2 -> c2<br />
sumCollects c1 c2 = foldr insert c2 (toList c1)<br />
</haskell><br />
<br />
<br />
== Definition of the type system extension ==<br />
<br />
['''NB:''' The following material will eventually become documentation for type families in the GHC User Manual. Please help to improve it by forwarding suggestions to <tt>tom.schrijvers@cs.kuleuven.be</tt>.]<br />
<br />
Type families appear in two flavours: (1) they can be defined on the toplevel or (2) they can appear inside type classes (in which case they are known as associated type synonyms). The former is the more general variant, as it lacks the requirement for the type-indexes to coincide with the class parameters. However, the later can lead to more clearly structured code and compiler warnings if some type instances were - possibly accidentally - omitted. In the following, we always discuss the general toplevel form first and then cover the additional constraints placed on associated types.<br />
<br />
=== Family declarations ===<br />
<br />
Indexed type families are introduced by a signature, such as <br />
<haskell><br />
type family Elem c :: *<br />
</haskell><br />
The special <hask>family</hask> distinguishes family from standard type declarations. The result kind annotation is optional and, as usual, defaults to <hask>*</hask> if omitted. An example is<br />
<haskell><br />
type family Elem c<br />
</haskell><br />
Named arguments can also be given explicit kind signatures if needed. Named arguments are _not_ optional.<br />
<br />
==== Associated family declarations ====<br />
<br />
When a type family is declared as part of a type class, we drop the <hask>family</hask> special. The <hask>Elem</hask> declaration takes the following form<br />
<haskell><br />
class Collects ce where<br />
type Elem ce :: *<br />
...<br />
</haskell><br />
The argument names of the type family must be class parameters. Each class parameter may only be used at most once per associated type, but some may be omitted and they may be in an order other than in the class head. Hence, the following contrieved example is admissible:<br />
<haskell><br />
class C a b c where<br />
type T c a :: *<br />
</haskell><br />
If kind signatures are required for argument variables, they need to be given in the class head.<br />
<br />
<br />
=== Instance declarations ===<br />
<br />
Instance declarations of type families are very similar to standard type synonym declarations. The only two differences are that the keyword <hask>type</hask> is followed by <hask>instance</hask> and that some or all of the type arguments can be non-variable types. For example, the <hask>[e]</hask> instance for <hask>Elem</hask> is<br />
<haskell><br />
type instance Elem [e] = e<br />
</haskell><br />
<br />
Type family instance declarations are only legitimate when an appropriate family declaration is in scope - just like class instances require the class declaration to be visible. Moreover, each instance declaration has to conform to the kind determined by its family declaration. This implies that the number of parameters of an instance declaration matches the arity determined by the kind of the family.<br />
<br />
Even if type families are defined as toplevel declarations, functions that perform different computations for different family instances still need to be defined as methods of type classes. In particular, the following is not possible:<br />
<haskell><br />
data family T a<br />
data instance T Int = A<br />
data instance T Char = B<br />
nonsence :: T a -> Int<br />
nonsence A = 1 -- WRONG: These two equations together...<br />
nonsence B = 2 -- ...will produce a type error.<br />
</haskell><br />
Given the functionality provided by GADTs (Generalised Algebraic Data Types), it might seem as if a definition, such as the above, should be feasible. However, type families are - in contrast to GADTs - are ''open''; i.e., new instances can always be added, possibly in other modules. Supporting pattern matching across different data instances would require a form of extensible case construct.<br />
<br />
==== Associated type instances ====<br />
<br />
When an associated family instance is declared within a type class instance, we drop the <hask>instance</hask> keyword in the family instance. So, the <hask>Either</hask> instance for <hask>GMap</hask> becomes:<br />
<haskell><br />
instance (GMapKey a, GMapKey b) => GMapKey (Either a b) where<br />
data GMap (Either a b) v = GMapEither (GMap a v) (GMap b v<br />
...<br />
</haskell><br />
The most important point about associated family instances is that the type indexes corresponding to class parameters must be identical to the type given in the instance head; here this is first argument of <hask>GMap</hask>, namely <hask>Either a b</hask>, which coincides with the only class parameter. Any parameters to the family constructor that do not correspond to class parameters, need to be variables in every instance; here this is the variable <hask>v</hask>.<br />
<br />
Instances for an associated family can only appear as part of instances declarations of the class in which the family was declared - just as with the equations of the methods of a class. Also in correspondence to how methods are handled, declarations of associated types can be omitted in class instances. If an associated family instance is omitted, the corresponding instance type is not inhabited; i.e., only diverging expressions, such as <hask>undefined</hask>, can assume the type.<br />
<br />
<br />
<br />
== Open issues ==<br />
<br />
<br />
None.</div>Tschrijvershttps://wiki.haskell.org/index.php?title=GHC/Type_families&diff=13220GHC/Type families2007-05-25T10:36:35Z<p>Tschrijvers: </p>
<hr />
<div>[[Category:GHC|Indexed types]]<br />
== Data and type families in GHC ==<br />
<br />
Data and type families are a new addition to GHC's type extensions. They are currently an '''experimental''' feature and so their design may still change to some degree. The current implementation covers ''data families'' (including newtypes), which can either be on the toplevel or inside class declarations - the latter are also known as [http://www.cse.unsw.edu.au/~chak/papers/CKPM05.html associated data types]. <br />
<br />
'''NB:''' Please note that type families (and hence also associated type synonyms) are '''not''' fully implemented yet. Any attempt to use them will lead to strange error messages. For the moment, you can only use <hask>data</hask> families.<br />
<br />
== What do I need to use data families? ==<br />
<br />
Indexed type families are implemented in GHC's HEAD (from version 6.7), which you can obtain in binary form from the [http://www.haskell.org/ghc/dist/current/dist/ nightly snapshots] or in source form from the [http://hackage.haskell.org/trac/ghc/wiki/Building/GettingTheSources source repository]. To enable indexed type families in GHC 6.7, you need to supply the compiler option <tt>-ftype-families</tt> (or <tt>-fglasgow-exts</tt>, which implies it). NB: The option used to be called <tt>-findexed-types</tt> for a while.<br />
<br />
== An associated data type example ==<br />
<br />
As an example, consider Ralf Hinze's [http://www.informatik.uni-bonn.de/~ralf/publications.html#J4 generalised tries], a form of generic finite maps. <br />
<br />
=== The class declaration ===<br />
<br />
We define a type class whose instances are the types that we can use as keys in our generic maps:<br />
<haskell><br />
class GMapKey k where<br />
data GMap k :: * -> *<br />
empty :: GMap k v<br />
lookup :: k -> GMap k v -> Maybe v<br />
insert :: k -> v -> GMap k v -> GMap k v<br />
</haskell><br />
The interesting part is the ''associated data family'' declaration of the class. It gives a [http://www.haskell.org/ghc/docs/latest/html/users_guide/type-extensions.html#sec-kinding ''kind signature''] (here <hask>* -> *</hask>) for the associated data type <hask>GMap k</hask> - analog to how methods receive a type signature in a class declaration.<br />
<br />
What it is important to notice is that the first parameter of the associated type <hask>GMap</hask> coincides with the class parameter of <hask>GMapKey</hask>. This indicates that also in all instances of the class, the instances of the associated data type need to have their first argument match up with the instance type. In general, the type arguments of an associated type can be a subset of the class parameters (in a multi-parameter type class) and they can appear in any order, possibly in an order other than in the class head. The latter can be useful if the associated data type is partially applied in some contexts.<br />
<br />
The second important point is that as <hask>GMap k</hask> has kind <hask>* -> *</hask> and <hask>k</hask> (implicitly) has kind <hask>*</hask>, the type constructor <hask>GMap</hask> (without an argument) has kind <hask>* -> * -> *</hask>. Consequently, we see that <hask>GMap</hask> is applied to two arguments in the signatures of the methods <hask>empty</hask>, <hask>lookup</hask>, and <hask>insert</hask>.<br />
<br />
=== An Int instance ===<br />
<br />
To use Ints as keys into generic maps, we declare an instance that simply uses <hask>Data.Map</hask>, thusly:<br />
<haskell><br />
instance GMapKey Int where<br />
data GMap Int v = GMapInt (Data.Map.Map Int v)<br />
empty = GMapInt Data.Map.empty<br />
lookup k (GMapInt m) = Data.Map.lookup k m<br />
insert k v (GMapInt m) = GMapInt (Data.Map.insert k v m)<br />
</haskell><br />
The <hask>Int</hask> instance of the associated data type <hask>GMap</hask> needs to have both of its parameters, but as only the first one corresponds to a class parameter, the second needs to be a type variable (here <hask>v</hask>). As mentioned before any associated type parameter that corresponds to a class parameter must be identical to the class parameter in each instance. The right hand side of the associated data declaration is like that of any other data type.<br />
<br />
NB: At the moment, GADT syntax is not allowed for associated data types (or other indexed types). This is not a fundemental limitation, but just a shortcoming of the current implementation, which we expect to lift in the future.<br />
<br />
As an exercise, implement an instance for <hask>Char</hask> that maps back to the <hask>Int</hask> instance using the conversion functions <hask>Char.ord</hask> and <hask>Char.chr</hask>.<br />
<br />
=== A unit instance ===<br />
<br />
Generic definitions, apart from elementary types, typically cover units, products, and sums. We start here with the unit instance for <hask>GMap</hask>:<br />
<haskell><br />
instance GMapKey () where<br />
data GMap () v = GMapUnit (Maybe v)<br />
empty = GMapUnit Nothing<br />
lookup () (GMapUnit v) = v<br />
insert () v (GMapUnit _) = GMapUnit $ Just v<br />
</haskell><br />
For unit, the map is just a <hask>Maybe</hask> value.<br />
<br />
=== Product and sum instances ===<br />
<br />
Nest, let us define the instances for pairs and sums (i.e., <hask>Either</hask>):<br />
<haskell><br />
instance (GMapKey a, GMapKey b) => GMapKey (a, b) where<br />
data GMap (a, b) v = GMapPair (GMap a (GMap b v))<br />
empty = GMapPair empty<br />
lookup (a, b) (GMapPair gm) = lookup a gm >>= lookup b <br />
insert (a, b) v (GMapPair gm) = GMapPair $ case lookup a gm of<br />
Nothing -> insert a (insert b v empty) gm<br />
Just gm2 -> insert a (insert b v gm2 ) gm<br />
<br />
instance (GMapKey a, GMapKey b) => GMapKey (Either a b) where<br />
data GMap (Either a b) v = GMapEither (GMap a v) (GMap b v)<br />
empty = GMapEither empty empty<br />
lookup (Left a) (GMapEither gm1 _gm2) = lookup a gm1<br />
lookup (Right b) (GMapEither _gm1 gm2 ) = lookup b gm2<br />
insert (Left a) v (GMapEither gm1 gm2) = GMapEither (insert a v gm1) gm2<br />
insert (Right a) v (GMapEither gm1 gm2) = GMapEither gm1 (insert a v gm2)<br />
</haskell><br />
If you find this code algorithmically surprising, I'd suggest to have a look at [http://www.informatik.uni-bonn.de/~ralf/publications.html#J4 Ralf Hinze's paper]. The only novelty concerning associated types, in these two instances, is that the instances have a context <hask>(GMapKey a, GMapKey b)</hask>. Consequently, the right hand sides of the associated type declarations can use <hask>GMap</hask> recursively at the key types <hask>a</hask> and <hask>b</hask> - not unlike the method definitions use the class methods recursively at the types for which the class is given in the instance context.<br />
<br />
=== Using a generic map ===<br />
<br />
Finally, some code building and quering a generic map:<br />
<haskell><br />
myGMap :: GMap (Int, Either Char ()) String<br />
myGMap = insert (5, Left 'c') "(5, Left 'c')" $<br />
insert (4, Right ()) "(4, Right ())" $<br />
insert (5, Right ()) "This is the one!" $<br />
insert (5, Right ()) "This is the two!" $<br />
insert (6, Right ()) "(6, Right ())" $<br />
insert (5, Left 'a') "(5, Left 'a')" $<br />
empty<br />
main = putStrLn $ maybe "Couldn't find key!" id $ lookup (5, Right ()) myGMap<br />
</haskell><br />
<br />
=== Download the code ===<br />
<br />
If you want to play with this example without copying it off the wiki, just download the [http://darcs.haskell.org/testsuite/tests/ghc-regress/indexed-types/should_run/GMapAssoc.hs source code for <hask>GMap</hask>] from GHC's test suite.<br />
<br />
== Definition of the type system extension ==<br />
<br />
['''NB:''' The following material will eventually become documentation for type families in the GHC User Manual. Please help to improve it by forwarding suggestions to <tt>chak@cse.unsw.edu.au</tt>.]<br />
<br />
Data families appear in two flavours: (1) they can be defined on the toplevel or (2) they can appear inside type classes (in which case they are known as associated types). The former is the more general variant, as it lacks the requirement for the type-indexes to coincide with the class parameters. However, the later can lead to more clearly structured code and compiler warnings if some type instances were - possibly accidentally - omitted. In the following, we always discuss the general toplevel form first and then cover the additional constraints placed on associated types.<br />
<br />
=== Family declarations ===<br />
<br />
Indexed data families are introduced by a signature, such as <br />
<haskell><br />
data family GMap k :: * -> *<br />
</haskell><br />
The special <hask>family</hask> distinguishes family from standard data declarations. The result kind annotation is optional and, as usual, defaults to <hask>*</hask> if omitted. An example is<br />
<haskell><br />
data family Array e<br />
</haskell><br />
Named arguments can also be given explicit kind signatures if needed. Just as with [http://www.haskell.org/ghc/docs/latest/html/users_guide/gadt.html GADT declarations] named arguments are entirely optional, so that we can declare <hask>Array</hask> alternatively with<br />
<haskell><br />
data family Array :: * -> *<br />
</haskell><br />
<br />
==== Associated family declarations ====<br />
<br />
When a data family is declared as part of a type class, we drop the <hask>family</hask> special. The <hask>GMap</hask> declaration takes the following form<br />
<haskell><br />
class GMapKey k where<br />
data GMap k :: * -> *<br />
...<br />
</haskell><br />
In contrast to toplevel declarations, named arguments must be used for all type parameters that are to be used as type-indexes. Moreover, the argument names must be class parameters. Each class parameter may only be used at most once per associated type, but some may be omitted and they may be in an order other than in the class head. Hence, the following contrieved example is admissible:<br />
<haskell><br />
class C a b c where<br />
data T c a :: *<br />
</haskell><br />
If kind signatures are required for argument variables, they need to be given in the class head.<br />
<br />
=== Instance declarations ===<br />
<br />
Instance declarations of data and newtype families are very similar to standard data and newtype declarations. The only two differences are that the keyword <hask>data</hask> or <hask>newtype</hask> is followed by <hask>instance</hask> and that some or all of the type arguments can be non-variable types. For example, the <hask>Either</hask> instance for <hask>GMap</hask> is<br />
<haskell><br />
data instance GMap (Either a b) v = GMapEither (GMap a v) (GMap b v)<br />
</haskell><br />
In this example, the declaration has only one variant. In general, it can be be any number.<br />
<br />
Data and newtype instance declarations are only legit when an appropriate family declaration is in scope - just like class instances require the class declaration to be visible. Moreover, each instance declaration has to conform to the kind determined by its family declaration. This implies that the number of parameters of an instance declaration matches the arity determined by the kind of the family. Although, all data families are declared with the <hask>data</hask> keyword, instances can be either <hask>data</hask> or <hask>newtype</hask>s, or a mix of both.<br />
<br />
Even if type families are defined as toplevel declarations, functions that perform different computations for different family instances still need to be defined as methods of type classes. In particular, the following is not possible:<br />
<haskell><br />
data family T a<br />
data instance T Int = A<br />
data instance T Char = B<br />
nonsence :: T a -> Int<br />
nonsence A = 1 -- WRONG: These two equations together...<br />
nonsence B = 2 -- ...will produce a type error.<br />
</haskell><br />
Given the functionality provided by GADTs (Generalised Algebraic Data Types), it might seem as if a definition, such as the above, should be feasible. However, type families are - in contrast to GADTs - are ''open''; i.e., new instances can always be added, possibly in other modules. Supporting pattern matching across different data instances would require a form of extensible case construct.<br />
<br />
==== Associated type instances ====<br />
<br />
When an associated family instance is declared within a type class instance, we drop the <hask>instance</hask> keyword in the family instance. So, the <hask>Either</hask> instance for <hask>GMap</hask> becomes:<br />
<haskell><br />
instance (GMapKey a, GMapKey b) => GMapKey (Either a b) where<br />
data GMap (Either a b) v = GMapEither (GMap a v) (GMap b v<br />
...<br />
</haskell><br />
The most important point about associated family instances is that the type indexes corresponding to class parameters must be identical to the type given in the instance head; here this is first argument of <hask>GMap</hask>, namely <hask>Either a b</hask>, which coincides with the only class parameter. Any parameters to the family constructor that do not correspond to class parameters, need to be variables in every instance; here this is the variable <hask>v</hask>.<br />
<br />
Instances for an associated family can only appear as part of instances declarations of the class in which the family was declared - just as with the equations of the methods of a class. Also in correspondence to how methods are handled, declarations of associated types can be omitted in class instances. If an associated family instance is omitted, the corresponding instance type is not inhabited; i.e., only diverging expressions, such as <hask>undefined</hask>, can assume the type.<br />
<br />
==== Class instances of type instances ====<br />
<br />
Type class instances of instances of data families can be defined as usual, and in particular data instance declarations can have <hask>deriving</hask> clauses. For example, we can write<br />
<haskell><br />
data GMap () v = GMapUnit (Maybe v)<br />
deriving Show<br />
</haskell><br />
which implcitly defines an instance of the form<br />
<haskell><br />
instance Show v => Show (GMap () v) where ...<br />
</haskell><br />
<br />
Note that class instances are always for particular ''instances'' of a data family and never for an entire family as a whole. This for essentially the same reasons that we cannot define a toplevel function that performs pattern matching on the data constructors of ''different'' instances of a single type family. It would require a form of extensible case construct.<br />
<br />
==== Overlap ====<br />
<br />
The instance declarations of a data family used in a single program may not overlap at all, independent of whether they are associated or not. In contrast to type class instances, this is not only a matter of consistency, but one of type safety.<br />
<br />
=== Import and export ===<br />
<br />
The association of data constructors with type families is more dynamic than that is the case with standard data and newtype declarations. In the standard case, the notation <hask>T(..)</hask> in an import or export list denotes the type constructor and all the data constructors introduced in its declaration. However, a family declaration never introduces any data constructors; instead, data constructors are introduced by family instances. As a result, which data constructors are associated with a type family depends on the currently visible instance declarations for that family. Consequently, an import or export item of the form <hask>T(..)</hask> denotes the family constructor and all currently visible data constructors - in the case of an export item, these may be either imported or defined in the current module. The treatment of import and export items that explicitly list data constructors, such as <hask>GMap(GMapEither)</hask>, is analogous.<br />
<br />
==== Associated families ====<br />
<br />
As expected, an import or export item of the form <hask>C(..)</hask> denotes all of the class' methods and associated types. However, when associated types are explicitly listed as subitems of a class, we need some new syntax, as uppercase identifiers as subitems are usually data constructors, not type constructors. To clarify that we denote types here, each associated type name needs to be prefixed by the keyword <hask>type</hask>. So for example, when explicitly listing the components of the <hask>GMapKey</hask> class, we write <hask>GMapKey(type GMap, empty, lookup, insert)</hask>.<br />
<br />
==== Examples ====<br />
<br />
Assuming our running <hask>GMapKey</hask> class example, let us look at some export lists and their meaning:<br />
<br />
* <hask>module GMap (GMapKey) where...</hask>: Exports just the class name.<br />
* <hask>module GMap (GMapKey(..)) where...</hask>: Exports the class, the associated type <hask>GMap</hask> and the member functions <hask>empty</hask>, <hask>lookup</hask>, and <hask>insert</hask>. None of the data constructors is exported.<br />
* <hask>module GMap (GMapKey(..), GMap(..)) where...</hask>: As before, but also exports all the data constructors <hask>GMapInt</hask>, <hask>GMapChar</hask>, <hask>GMapUnit</hask>, <hask>GMapPair</hask>, and <hask>GMapUnit</hask>.<br />
* <hask>module GMap (GMapKey(empty, lookup, insert), GMap(..)) where...</hask>: As before.<br />
* <hask>module GMap (GMapKey, empty, lookup, insert, GMap(..)) where...</hask>: As before.<br />
<br />
Finally, you can write <hask>GMapKey(type GMap)</hask> to denote both the class <hask>GMapKey</hask> as well as its associated type <hask>GMap</hask>. However, you cannot write <hask>GMapKey(type GMap(..))</hask> &mdash; i.e., sub-component specifications cannot be nested. To specify <hask>GMap</hask>'s data constructors, you have to list it separately.<br />
<br />
==== Instances ====<br />
<br />
Family instances are implicitly exported, just like class instances. However, this applies only to the heads of instances, not to the data constructors an instance defines.<br />
<br />
<br />
== A associated type synonym example ==<br />
<br />
Associated data types ar much better behaved than<br />
functional dependencies. Hence, GHC's type checking and inference are<br />
more powerful. Here is an example of how to port your existing functional <br />
depenency programs to associated type synonyms.<br />
<br />
=== The <hask>class</hask> declaration ===<br />
<br />
Here's an example from the original Functional Dependencies paper:<br />
<haskell><br />
class Collects e ce | ce -> e where<br />
empty :: ce<br />
insert :: e -> ce -> ce<br />
member :: e -> ce -> Bool<br />
toList :: ce -> [e]<br />
</haskell><br />
<br />
With associated type synonyms we can write this as:<br />
<haskell><br />
class Collects ce where<br />
type Elem ce<br />
empty :: ce<br />
insert :: Elem ce -> ce -> ce<br />
member :: Elem ce -> ce -> Bool<br />
toList :: ce -> [Elem ce]<br />
</haskell><br />
That's right, we have dropped from a multi-paramter type class<br />
to a single parameter type class. The parameter <hask>e</hask><br />
has become an associated type <hask>Elem ce</hask>.<br />
<br />
=== An <hask>instance</hask>===<br />
<br />
Here's an instance, with functional dependencies:<br />
<haskell><br />
instance Eq e => Collects e [e] where<br />
empty = []<br />
insert e l = (e:l)<br />
member e [] = False<br />
member e (x:xs) | e == x = True<br />
| otherwise = member e xs<br />
toList l = l<br />
</haskell><br />
<br />
With associated type synonyms, this becomes:<br />
<haskell><br />
instance Eq e => Collects [e] where<br />
type Elem [e] = e<br />
empty = []<br />
insert e l = (e:l)<br />
member e [] = False<br />
member e (x:xs) | e == x = True<br />
| otherwise = member e xs<br />
toList l = l<br />
</haskell><br />
<br />
=== Using generic collections ===<br />
<br />
With Functional Dependencies the code would be:<br />
<haskell><br />
sumCollects :: (Collects e c1,Collects e c2) => c1 -> c2 -> c2<br />
sumCollects c1 c2 = foldr insert c2 (toList c1)<br />
</haskell><br />
<br />
In contrast, with associated type synonyms, we get:<br />
<haskell><br />
sumCollects :: (Collects c1,Collects c2,Elem c1 ~ Elem c2) => c1 -> c2 -> c2<br />
sumCollects c1 c2 = foldr insert c2 (toList c1)<br />
</haskell><br />
<br />
<br />
== Definition of the type system extension ==<br />
<br />
['''NB:''' The following material will eventually become documentation for type families in the GHC User Manual. Please help to improve it by forwarding suggestions to <tt>tom.schrijvers@cs.kuleuven.be</tt>.]<br />
<br />
Type families appear in two flavours: (1) they can be defined on the toplevel or (2) they can appear inside type classes (in which case they are known as associated type synonyms). The former is the more general variant, as it lacks the requirement for the type-indexes to coincide with the class parameters. However, the later can lead to more clearly structured code and compiler warnings if some type instances were - possibly accidentally - omitted. In the following, we always discuss the general toplevel form first and then cover the additional constraints placed on associated types.<br />
<br />
=== Family declarations ===<br />
<br />
Indexed type families are introduced by a signature, such as <br />
<haskell><br />
type family Elem c :: *<br />
</haskell><br />
The special <hask>family</hask> distinguishes family from standard type declarations. The result kind annotation is optional and, as usual, defaults to <hask>*</hask> if omitted. An example is<br />
<haskell><br />
type family Elem c<br />
</haskell><br />
Named arguments can also be given explicit kind signatures if needed. Named arguments are _not_ optional.<br />
<br />
==== Associated family declarations ====<br />
<br />
When a type family is declared as part of a type class, we drop the <hask>family</hask> special. The <hask>Elem</hask> declaration takes the following form<br />
<haskell><br />
class Collects ce where<br />
type Elem ce :: *<br />
...<br />
</haskell><br />
The argument names of the type family must be class parameters. Each class parameter may only be used at most once per associated type, but some may be omitted and they may be in an order other than in the class head. Hence, the following contrieved example is admissible:<br />
<haskell><br />
class C a b c where<br />
type T c a :: *<br />
</haskell><br />
If kind signatures are required for argument variables, they need to be given in the class head.<br />
<br />
<br />
=== Instance declarations ===<br />
<br />
Instance declarations of data and newtype families are very similar to standard data and newtype declarations. The only two differences are that the keyword <hask>data</hask> or <hask>newtype</hask> is followed by <hask>instance</hask> and that some or all of the type arguments can be non-variable types. For example, the <hask>Either</hask> instance for <hask>GMap</hask> is<br />
<haskell><br />
data instance GMap (Either a b) v = GMapEither (GMap a v) (GMap b v)<br />
</haskell><br />
In this example, the declaration has only one variant. In general, it can be be any number.<br />
<br />
Data and newtype instance declarations are only legit when an appropriate family declaration is in scope - just like class instances require the class declaration to be visible. Moreover, each instance declaration has to conform to the kind determined by its family declaration. This implies that the number of parameters of an instance declaration matches the arity determined by the kind of the family. Although, all data families are declared with the <hask>data</hask> keyword, instances can be either <hask>data</hask> or <hask>newtype</hask>s, or a mix of both.<br />
<br />
Even if type families are defined as toplevel declarations, functions that perform different computations for different family instances still need to be defined as methods of type classes. In particular, the following is not possible:<br />
<haskell><br />
data family T a<br />
data instance T Int = A<br />
data instance T Char = B<br />
nonsence :: T a -> Int<br />
nonsence A = 1 -- WRONG: These two equations together...<br />
nonsence B = 2 -- ...will produce a type error.<br />
</haskell><br />
Given the functionality provided by GADTs (Generalised Algebraic Data Types), it might seem as if a definition, such as the above, should be feasible. However, type families are - in contrast to GADTs - are ''open''; i.e., new instances can always be added, possibly in other modules. Supporting pattern matching across different data instances would require a form of extensible case construct.<br />
<br />
==== Associated type instances ====<br />
<br />
When an associated family instance is declared within a type class instance, we drop the <hask>instance</hask> keyword in the family instance. So, the <hask>Either</hask> instance for <hask>GMap</hask> becomes:<br />
<haskell><br />
instance (GMapKey a, GMapKey b) => GMapKey (Either a b) where<br />
data GMap (Either a b) v = GMapEither (GMap a v) (GMap b v<br />
...<br />
</haskell><br />
The most important point about associated family instances is that the type indexes corresponding to class parameters must be identical to the type given in the instance head; here this is first argument of <hask>GMap</hask>, namely <hask>Either a b</hask>, which coincides with the only class parameter. Any parameters to the family constructor that do not correspond to class parameters, need to be variables in every instance; here this is the variable <hask>v</hask>.<br />
<br />
Instances for an associated family can only appear as part of instances declarations of the class in which the family was declared - just as with the equations of the methods of a class. Also in correspondence to how methods are handled, declarations of associated types can be omitted in class instances. If an associated family instance is omitted, the corresponding instance type is not inhabited; i.e., only diverging expressions, such as <hask>undefined</hask>, can assume the type.<br />
<br />
<br />
<br />
== Open issues ==<br />
<br />
<br />
None.</div>Tschrijvershttps://wiki.haskell.org/index.php?title=GHC/Type_families&diff=13219GHC/Type families2007-05-25T10:33:53Z<p>Tschrijvers: </p>
<hr />
<div>[[Category:GHC|Indexed types]]<br />
== Data and type families in GHC ==<br />
<br />
Data and type families are a new addition to GHC's type extensions. They are currently an '''experimental''' feature and so their design may still change to some degree. The current implementation covers ''data families'' (including newtypes), which can either be on the toplevel or inside class declarations - the latter are also known as [http://www.cse.unsw.edu.au/~chak/papers/CKPM05.html associated data types]. <br />
<br />
'''NB:''' Please note that type families (and hence also associated type synonyms) are '''not''' fully implemented yet. Any attempt to use them will lead to strange error messages. For the moment, you can only use <hask>data</hask> families.<br />
<br />
== What do I need to use data families? ==<br />
<br />
Indexed type families are implemented in GHC's HEAD (from version 6.7), which you can obtain in binary form from the [http://www.haskell.org/ghc/dist/current/dist/ nightly snapshots] or in source form from the [http://hackage.haskell.org/trac/ghc/wiki/Building/GettingTheSources source repository]. To enable indexed type families in GHC 6.7, you need to supply the compiler option <tt>-ftype-families</tt> (or <tt>-fglasgow-exts</tt>, which implies it). NB: The option used to be called <tt>-findexed-types</tt> for a while.<br />
<br />
== An associated data type example ==<br />
<br />
As an example, consider Ralf Hinze's [http://www.informatik.uni-bonn.de/~ralf/publications.html#J4 generalised tries], a form of generic finite maps. <br />
<br />
=== The class declaration ===<br />
<br />
We define a type class whose instances are the types that we can use as keys in our generic maps:<br />
<haskell><br />
class GMapKey k where<br />
data GMap k :: * -> *<br />
empty :: GMap k v<br />
lookup :: k -> GMap k v -> Maybe v<br />
insert :: k -> v -> GMap k v -> GMap k v<br />
</haskell><br />
The interesting part is the ''associated data family'' declaration of the class. It gives a [http://www.haskell.org/ghc/docs/latest/html/users_guide/type-extensions.html#sec-kinding ''kind signature''] (here <hask>* -> *</hask>) for the associated data type <hask>GMap k</hask> - analog to how methods receive a type signature in a class declaration.<br />
<br />
What it is important to notice is that the first parameter of the associated type <hask>GMap</hask> coincides with the class parameter of <hask>GMapKey</hask>. This indicates that also in all instances of the class, the instances of the associated data type need to have their first argument match up with the instance type. In general, the type arguments of an associated type can be a subset of the class parameters (in a multi-parameter type class) and they can appear in any order, possibly in an order other than in the class head. The latter can be useful if the associated data type is partially applied in some contexts.<br />
<br />
The second important point is that as <hask>GMap k</hask> has kind <hask>* -> *</hask> and <hask>k</hask> (implicitly) has kind <hask>*</hask>, the type constructor <hask>GMap</hask> (without an argument) has kind <hask>* -> * -> *</hask>. Consequently, we see that <hask>GMap</hask> is applied to two arguments in the signatures of the methods <hask>empty</hask>, <hask>lookup</hask>, and <hask>insert</hask>.<br />
<br />
=== An Int instance ===<br />
<br />
To use Ints as keys into generic maps, we declare an instance that simply uses <hask>Data.Map</hask>, thusly:<br />
<haskell><br />
instance GMapKey Int where<br />
data GMap Int v = GMapInt (Data.Map.Map Int v)<br />
empty = GMapInt Data.Map.empty<br />
lookup k (GMapInt m) = Data.Map.lookup k m<br />
insert k v (GMapInt m) = GMapInt (Data.Map.insert k v m)<br />
</haskell><br />
The <hask>Int</hask> instance of the associated data type <hask>GMap</hask> needs to have both of its parameters, but as only the first one corresponds to a class parameter, the second needs to be a type variable (here <hask>v</hask>). As mentioned before any associated type parameter that corresponds to a class parameter must be identical to the class parameter in each instance. The right hand side of the associated data declaration is like that of any other data type.<br />
<br />
NB: At the moment, GADT syntax is not allowed for associated data types (or other indexed types). This is not a fundemental limitation, but just a shortcoming of the current implementation, which we expect to lift in the future.<br />
<br />
As an exercise, implement an instance for <hask>Char</hask> that maps back to the <hask>Int</hask> instance using the conversion functions <hask>Char.ord</hask> and <hask>Char.chr</hask>.<br />
<br />
=== A unit instance ===<br />
<br />
Generic definitions, apart from elementary types, typically cover units, products, and sums. We start here with the unit instance for <hask>GMap</hask>:<br />
<haskell><br />
instance GMapKey () where<br />
data GMap () v = GMapUnit (Maybe v)<br />
empty = GMapUnit Nothing<br />
lookup () (GMapUnit v) = v<br />
insert () v (GMapUnit _) = GMapUnit $ Just v<br />
</haskell><br />
For unit, the map is just a <hask>Maybe</hask> value.<br />
<br />
=== Product and sum instances ===<br />
<br />
Nest, let us define the instances for pairs and sums (i.e., <hask>Either</hask>):<br />
<haskell><br />
instance (GMapKey a, GMapKey b) => GMapKey (a, b) where<br />
data GMap (a, b) v = GMapPair (GMap a (GMap b v))<br />
empty = GMapPair empty<br />
lookup (a, b) (GMapPair gm) = lookup a gm >>= lookup b <br />
insert (a, b) v (GMapPair gm) = GMapPair $ case lookup a gm of<br />
Nothing -> insert a (insert b v empty) gm<br />
Just gm2 -> insert a (insert b v gm2 ) gm<br />
<br />
instance (GMapKey a, GMapKey b) => GMapKey (Either a b) where<br />
data GMap (Either a b) v = GMapEither (GMap a v) (GMap b v)<br />
empty = GMapEither empty empty<br />
lookup (Left a) (GMapEither gm1 _gm2) = lookup a gm1<br />
lookup (Right b) (GMapEither _gm1 gm2 ) = lookup b gm2<br />
insert (Left a) v (GMapEither gm1 gm2) = GMapEither (insert a v gm1) gm2<br />
insert (Right a) v (GMapEither gm1 gm2) = GMapEither gm1 (insert a v gm2)<br />
</haskell><br />
If you find this code algorithmically surprising, I'd suggest to have a look at [http://www.informatik.uni-bonn.de/~ralf/publications.html#J4 Ralf Hinze's paper]. The only novelty concerning associated types, in these two instances, is that the instances have a context <hask>(GMapKey a, GMapKey b)</hask>. Consequently, the right hand sides of the associated type declarations can use <hask>GMap</hask> recursively at the key types <hask>a</hask> and <hask>b</hask> - not unlike the method definitions use the class methods recursively at the types for which the class is given in the instance context.<br />
<br />
=== Using a generic map ===<br />
<br />
Finally, some code building and quering a generic map:<br />
<haskell><br />
myGMap :: GMap (Int, Either Char ()) String<br />
myGMap = insert (5, Left 'c') "(5, Left 'c')" $<br />
insert (4, Right ()) "(4, Right ())" $<br />
insert (5, Right ()) "This is the one!" $<br />
insert (5, Right ()) "This is the two!" $<br />
insert (6, Right ()) "(6, Right ())" $<br />
insert (5, Left 'a') "(5, Left 'a')" $<br />
empty<br />
main = putStrLn $ maybe "Couldn't find key!" id $ lookup (5, Right ()) myGMap<br />
</haskell><br />
<br />
=== Download the code ===<br />
<br />
If you want to play with this example without copying it off the wiki, just download the [http://darcs.haskell.org/testsuite/tests/ghc-regress/indexed-types/should_run/GMapAssoc.hs source code for <hask>GMap</hask>] from GHC's test suite.<br />
<br />
== Definition of the type system extension ==<br />
<br />
['''NB:''' The following material will eventually become documentation for type families in the GHC User Manual. Please help to improve it by forwarding suggestions to <tt>chak@cse.unsw.edu.au</tt>.]<br />
<br />
Data families appear in two flavours: (1) they can be defined on the toplevel or (2) they can appear inside type classes (in which case they are known as associated types). The former is the more general variant, as it lacks the requirement for the type-indexes to coincide with the class parameters. However, the later can lead to more clearly structured code and compiler warnings if some type instances were - possibly accidentally - omitted. In the following, we always discuss the general toplevel form first and then cover the additional constraints placed on associated types.<br />
<br />
=== Family declarations ===<br />
<br />
Indexed data families are introduced by a signature, such as <br />
<haskell><br />
data family GMap k :: * -> *<br />
</haskell><br />
The special <hask>family</hask> distinguishes family from standard data declarations. The result kind annotation is optional and, as usual, defaults to <hask>*</hask> if omitted. An example is<br />
<haskell><br />
data family Array e<br />
</haskell><br />
Named arguments can also be given explicit kind signatures if needed. Just as with [http://www.haskell.org/ghc/docs/latest/html/users_guide/gadt.html GADT declarations] named arguments are entirely optional, so that we can declare <hask>Array</hask> alternatively with<br />
<haskell><br />
data family Array :: * -> *<br />
</haskell><br />
<br />
==== Associated family declarations ====<br />
<br />
When a data family is declared as part of a type class, we drop the <hask>family</hask> special. The <hask>GMap</hask> declaration takes the following form<br />
<haskell><br />
class GMapKey k where<br />
data GMap k :: * -> *<br />
...<br />
</haskell><br />
In contrast to toplevel declarations, named arguments must be used for all type parameters that are to be used as type-indexes. Moreover, the argument names must be class parameters. Each class parameter may only be used at most once per associated type, but some may be omitted and they may be in an order other than in the class head. Hence, the following contrieved example is admissible:<br />
<haskell><br />
class C a b c where<br />
data T c a :: *<br />
</haskell><br />
If kind signatures are required for argument variables, they need to be given in the class head.<br />
<br />
=== Instance declarations ===<br />
<br />
Instance declarations of data and newtype families are very similar to standard data and newtype declarations. The only two differences are that the keyword <hask>data</hask> or <hask>newtype</hask> is followed by <hask>instance</hask> and that some or all of the type arguments can be non-variable types. For example, the <hask>Either</hask> instance for <hask>GMap</hask> is<br />
<haskell><br />
data instance GMap (Either a b) v = GMapEither (GMap a v) (GMap b v)<br />
</haskell><br />
In this example, the declaration has only one variant. In general, it can be be any number.<br />
<br />
Data and newtype instance declarations are only legit when an appropriate family declaration is in scope - just like class instances require the class declaration to be visible. Moreover, each instance declaration has to conform to the kind determined by its family declaration. This implies that the number of parameters of an instance declaration matches the arity determined by the kind of the family. Although, all data families are declared with the <hask>data</hask> keyword, instances can be either <hask>data</hask> or <hask>newtype</hask>s, or a mix of both.<br />
<br />
Even if type families are defined as toplevel declarations, functions that perform different computations for different family instances still need to be defined as methods of type classes. In particular, the following is not possible:<br />
<haskell><br />
data family T a<br />
data instance T Int = A<br />
data instance T Char = B<br />
nonsence :: T a -> Int<br />
nonsence A = 1 -- WRONG: These two equations together...<br />
nonsence B = 2 -- ...will produce a type error.<br />
</haskell><br />
Given the functionality provided by GADTs (Generalised Algebraic Data Types), it might seem as if a definition, such as the above, should be feasible. However, type families are - in contrast to GADTs - are ''open''; i.e., new instances can always be added, possibly in other modules. Supporting pattern matching across different data instances would require a form of extensible case construct.<br />
<br />
==== Associated type instances ====<br />
<br />
When an associated family instance is declared within a type class instance, we drop the <hask>instance</hask> keyword in the family instance. So, the <hask>Either</hask> instance for <hask>GMap</hask> becomes:<br />
<haskell><br />
instance (GMapKey a, GMapKey b) => GMapKey (Either a b) where<br />
data GMap (Either a b) v = GMapEither (GMap a v) (GMap b v<br />
...<br />
</haskell><br />
The most important point about associated family instances is that the type indexes corresponding to class parameters must be identical to the type given in the instance head; here this is first argument of <hask>GMap</hask>, namely <hask>Either a b</hask>, which coincides with the only class parameter. Any parameters to the family constructor that do not correspond to class parameters, need to be variables in every instance; here this is the variable <hask>v</hask>.<br />
<br />
Instances for an associated family can only appear as part of instances declarations of the class in which the family was declared - just as with the equations of the methods of a class. Also in correspondence to how methods are handled, declarations of associated types can be omitted in class instances. If an associated family instance is omitted, the corresponding instance type is not inhabited; i.e., only diverging expressions, such as <hask>undefined</hask>, can assume the type.<br />
<br />
==== Class instances of type instances ====<br />
<br />
Type class instances of instances of data families can be defined as usual, and in particular data instance declarations can have <hask>deriving</hask> clauses. For example, we can write<br />
<haskell><br />
data GMap () v = GMapUnit (Maybe v)<br />
deriving Show<br />
</haskell><br />
which implcitly defines an instance of the form<br />
<haskell><br />
instance Show v => Show (GMap () v) where ...<br />
</haskell><br />
<br />
Note that class instances are always for particular ''instances'' of a data family and never for an entire family as a whole. This for essentially the same reasons that we cannot define a toplevel function that performs pattern matching on the data constructors of ''different'' instances of a single type family. It would require a form of extensible case construct.<br />
<br />
==== Overlap ====<br />
<br />
The instance declarations of a data family used in a single program may not overlap at all, independent of whether they are associated or not. In contrast to type class instances, this is not only a matter of consistency, but one of type safety.<br />
<br />
=== Import and export ===<br />
<br />
The association of data constructors with type families is more dynamic than that is the case with standard data and newtype declarations. In the standard case, the notation <hask>T(..)</hask> in an import or export list denotes the type constructor and all the data constructors introduced in its declaration. However, a family declaration never introduces any data constructors; instead, data constructors are introduced by family instances. As a result, which data constructors are associated with a type family depends on the currently visible instance declarations for that family. Consequently, an import or export item of the form <hask>T(..)</hask> denotes the family constructor and all currently visible data constructors - in the case of an export item, these may be either imported or defined in the current module. The treatment of import and export items that explicitly list data constructors, such as <hask>GMap(GMapEither)</hask>, is analogous.<br />
<br />
==== Associated families ====<br />
<br />
As expected, an import or export item of the form <hask>C(..)</hask> denotes all of the class' methods and associated types. However, when associated types are explicitly listed as subitems of a class, we need some new syntax, as uppercase identifiers as subitems are usually data constructors, not type constructors. To clarify that we denote types here, each associated type name needs to be prefixed by the keyword <hask>type</hask>. So for example, when explicitly listing the components of the <hask>GMapKey</hask> class, we write <hask>GMapKey(type GMap, empty, lookup, insert)</hask>.<br />
<br />
==== Examples ====<br />
<br />
Assuming our running <hask>GMapKey</hask> class example, let us look at some export lists and their meaning:<br />
<br />
* <hask>module GMap (GMapKey) where...</hask>: Exports just the class name.<br />
* <hask>module GMap (GMapKey(..)) where...</hask>: Exports the class, the associated type <hask>GMap</hask> and the member functions <hask>empty</hask>, <hask>lookup</hask>, and <hask>insert</hask>. None of the data constructors is exported.<br />
* <hask>module GMap (GMapKey(..), GMap(..)) where...</hask>: As before, but also exports all the data constructors <hask>GMapInt</hask>, <hask>GMapChar</hask>, <hask>GMapUnit</hask>, <hask>GMapPair</hask>, and <hask>GMapUnit</hask>.<br />
* <hask>module GMap (GMapKey(empty, lookup, insert), GMap(..)) where...</hask>: As before.<br />
* <hask>module GMap (GMapKey, empty, lookup, insert, GMap(..)) where...</hask>: As before.<br />
<br />
Finally, you can write <hask>GMapKey(type GMap)</hask> to denote both the class <hask>GMapKey</hask> as well as its associated type <hask>GMap</hask>. However, you cannot write <hask>GMapKey(type GMap(..))</hask> &mdash; i.e., sub-component specifications cannot be nested. To specify <hask>GMap</hask>'s data constructors, you have to list it separately.<br />
<br />
==== Instances ====<br />
<br />
Family instances are implicitly exported, just like class instances. However, this applies only to the heads of instances, not to the data constructors an instance defines.<br />
<br />
<br />
== A associated type synonym example ==<br />
<br />
Associated data types ar much better behaved than<br />
functional dependencies. Hence, GHC's type checking and inference are<br />
more powerful. Here is an example of how to port your existing functional <br />
depenency programs to associated type synonyms.<br />
<br />
=== The <hask>class</hask> declaration ===<br />
<br />
Here's an example from the original Functional Dependencies paper:<br />
<haskell><br />
class Collects e ce | ce -> e where<br />
empty :: ce<br />
insert :: e -> ce -> ce<br />
member :: e -> ce -> Bool<br />
toList :: ce -> [e]<br />
</haskell><br />
<br />
With associated type synonyms we can write this as:<br />
<haskell><br />
class Collects ce where<br />
type Elem ce<br />
empty :: ce<br />
insert :: Elem ce -> ce -> ce<br />
member :: Elem ce -> ce -> Bool<br />
toList :: ce -> [Elem ce]<br />
</haskell><br />
That's right, we have dropped from a multi-paramter type class<br />
to a single parameter type class. The parameter <hask>e</hask><br />
has become an associated type <hask>Elem ce</hask>.<br />
<br />
=== An <hask>instance</hask>===<br />
<br />
Here's an instance, with functional dependencies:<br />
<haskell><br />
instance Eq e => Collects e [e] where<br />
empty = []<br />
insert e l = (e:l)<br />
member e [] = False<br />
member e (x:xs) | e == x = True<br />
| otherwise = member e xs<br />
toList l = l<br />
</haskell><br />
<br />
With associated type synonyms, this becomes:<br />
<haskell><br />
instance Eq e => Collects [e] where<br />
type Elem [e] = e<br />
empty = []<br />
insert e l = (e:l)<br />
member e [] = False<br />
member e (x:xs) | e == x = True<br />
| otherwise = member e xs<br />
toList l = l<br />
</haskell><br />
<br />
=== Using generic collections ===<br />
<br />
With Functional Dependencies the code would be:<br />
<haskell><br />
sumCollects :: (Collects e c1,Collects e c2) => c1 -> c2 -> c2<br />
sumCollects c1 c2 = foldr insert c2 (toList c1)<br />
</haskell><br />
<br />
In contrast, with associated type synonyms, we get:<br />
<haskell><br />
sumCollects :: (Collects c1,Collects c2,Elem c1 ~ Elem c2) => c1 -> c2 -> c2<br />
sumCollects c1 c2 = foldr insert c2 (toList c1)<br />
</haskell><br />
<br />
<br />
== Definition of the type system extension ==<br />
<br />
['''NB:''' The following material will eventually become documentation for type families in the GHC User Manual. Please help to improve it by forwarding suggestions to <tt>tom.schrijvers@cs.kuleuven.be</tt>.]<br />
<br />
Type families appear in two flavours: (1) they can be defined on the toplevel or (2) they can appear inside type classes (in which case they are known as associated type synonyms). The former is the more general variant, as it lacks the requirement for the type-indexes to coincide with the class parameters. However, the later can lead to more clearly structured code and compiler warnings if some type instances were - possibly accidentally - omitted. In the following, we always discuss the general toplevel form first and then cover the additional constraints placed on associated types.<br />
<br />
=== Family declarations ===<br />
<br />
Indexed type families are introduced by a signature, such as <br />
<haskell><br />
type family Elem c :: *<br />
</haskell><br />
The special <hask>family</hask> distinguishes family from standard type declarations. The result kind annotation is optional and, as usual, defaults to <hask>*</hask> if omitted. An example is<br />
<haskell><br />
type family Elem c<br />
</haskell><br />
Named arguments can also be given explicit kind signatures if needed. Named arguments are _not_ optional.<br />
<br />
==== Associated family declarations ====<br />
<br />
When a type family is declared as part of a type class, we drop the <hask>family</hask> special. The <hask>Elem</hask> declaration takes the following form<br />
<haskell><br />
class Collects ce where<br />
type Elem ce :: *<br />
...<br />
</haskell><br />
The argument names of the type family must be class parameters. Each class parameter may only be used at most once per associated type, but some may be omitted and they may be in an order other than in the class head. Hence, the following contrieved example is admissible:<br />
<haskell><br />
class C a b c where<br />
type T c a :: *<br />
</haskell><br />
If kind signatures are required for argument variables, they need to be given in the class head.<br />
<br />
<br />
== Open issues ==<br />
<br />
<br />
None.</div>Tschrijvershttps://wiki.haskell.org/index.php?title=GHC/Type_families&diff=13218GHC/Type families2007-05-25T09:36:16Z<p>Tschrijvers: </p>
<hr />
<div>[[Category:GHC|Indexed types]]<br />
== Data and type families in GHC ==<br />
<br />
Data and type families are a new addition to GHC's type extensions. They are currently an '''experimental''' feature and so their design may still change to some degree. The current implementation covers ''data families'' (including newtypes), which can either be on the toplevel or inside class declarations - the latter are also known as [http://www.cse.unsw.edu.au/~chak/papers/CKPM05.html associated data types]. <br />
<br />
'''NB:''' Please note that type families (and hence also associated type synonyms) are '''not''' fully implemented yet. Any attempt to use them will lead to strange error messages. For the moment, you can only use <hask>data</hask> families.<br />
<br />
== What do I need to use data families? ==<br />
<br />
Indexed type families are implemented in GHC's HEAD (from version 6.7), which you can obtain in binary form from the [http://www.haskell.org/ghc/dist/current/dist/ nightly snapshots] or in source form from the [http://hackage.haskell.org/trac/ghc/wiki/Building/GettingTheSources source repository]. To enable indexed type families in GHC 6.7, you need to supply the compiler option <tt>-ftype-families</tt> (or <tt>-fglasgow-exts</tt>, which implies it). NB: The option used to be called <tt>-findexed-types</tt> for a while.<br />
<br />
== An associated data type example ==<br />
<br />
As an example, consider Ralf Hinze's [http://www.informatik.uni-bonn.de/~ralf/publications.html#J4 generalised tries], a form of generic finite maps. <br />
<br />
=== The class declaration ===<br />
<br />
We define a type class whose instances are the types that we can use as keys in our generic maps:<br />
<haskell><br />
class GMapKey k where<br />
data GMap k :: * -> *<br />
empty :: GMap k v<br />
lookup :: k -> GMap k v -> Maybe v<br />
insert :: k -> v -> GMap k v -> GMap k v<br />
</haskell><br />
The interesting part is the ''associated data family'' declaration of the class. It gives a [http://www.haskell.org/ghc/docs/latest/html/users_guide/type-extensions.html#sec-kinding ''kind signature''] (here <hask>* -> *</hask>) for the associated data type <hask>GMap k</hask> - analog to how methods receive a type signature in a class declaration.<br />
<br />
What it is important to notice is that the first parameter of the associated type <hask>GMap</hask> coincides with the class parameter of <hask>GMapKey</hask>. This indicates that also in all instances of the class, the instances of the associated data type need to have their first argument match up with the instance type. In general, the type arguments of an associated type can be a subset of the class parameters (in a multi-parameter type class) and they can appear in any order, possibly in an order other than in the class head. The latter can be useful if the associated data type is partially applied in some contexts.<br />
<br />
The second important point is that as <hask>GMap k</hask> has kind <hask>* -> *</hask> and <hask>k</hask> (implicitly) has kind <hask>*</hask>, the type constructor <hask>GMap</hask> (without an argument) has kind <hask>* -> * -> *</hask>. Consequently, we see that <hask>GMap</hask> is applied to two arguments in the signatures of the methods <hask>empty</hask>, <hask>lookup</hask>, and <hask>insert</hask>.<br />
<br />
=== An Int instance ===<br />
<br />
To use Ints as keys into generic maps, we declare an instance that simply uses <hask>Data.Map</hask>, thusly:<br />
<haskell><br />
instance GMapKey Int where<br />
data GMap Int v = GMapInt (Data.Map.Map Int v)<br />
empty = GMapInt Data.Map.empty<br />
lookup k (GMapInt m) = Data.Map.lookup k m<br />
insert k v (GMapInt m) = GMapInt (Data.Map.insert k v m)<br />
</haskell><br />
The <hask>Int</hask> instance of the associated data type <hask>GMap</hask> needs to have both of its parameters, but as only the first one corresponds to a class parameter, the second needs to be a type variable (here <hask>v</hask>). As mentioned before any associated type parameter that corresponds to a class parameter must be identical to the class parameter in each instance. The right hand side of the associated data declaration is like that of any other data type.<br />
<br />
NB: At the moment, GADT syntax is not allowed for associated data types (or other indexed types). This is not a fundemental limitation, but just a shortcoming of the current implementation, which we expect to lift in the future.<br />
<br />
As an exercise, implement an instance for <hask>Char</hask> that maps back to the <hask>Int</hask> instance using the conversion functions <hask>Char.ord</hask> and <hask>Char.chr</hask>.<br />
<br />
=== A unit instance ===<br />
<br />
Generic definitions, apart from elementary types, typically cover units, products, and sums. We start here with the unit instance for <hask>GMap</hask>:<br />
<haskell><br />
instance GMapKey () where<br />
data GMap () v = GMapUnit (Maybe v)<br />
empty = GMapUnit Nothing<br />
lookup () (GMapUnit v) = v<br />
insert () v (GMapUnit _) = GMapUnit $ Just v<br />
</haskell><br />
For unit, the map is just a <hask>Maybe</hask> value.<br />
<br />
=== Product and sum instances ===<br />
<br />
Nest, let us define the instances for pairs and sums (i.e., <hask>Either</hask>):<br />
<haskell><br />
instance (GMapKey a, GMapKey b) => GMapKey (a, b) where<br />
data GMap (a, b) v = GMapPair (GMap a (GMap b v))<br />
empty = GMapPair empty<br />
lookup (a, b) (GMapPair gm) = lookup a gm >>= lookup b <br />
insert (a, b) v (GMapPair gm) = GMapPair $ case lookup a gm of<br />
Nothing -> insert a (insert b v empty) gm<br />
Just gm2 -> insert a (insert b v gm2 ) gm<br />
<br />
instance (GMapKey a, GMapKey b) => GMapKey (Either a b) where<br />
data GMap (Either a b) v = GMapEither (GMap a v) (GMap b v)<br />
empty = GMapEither empty empty<br />
lookup (Left a) (GMapEither gm1 _gm2) = lookup a gm1<br />
lookup (Right b) (GMapEither _gm1 gm2 ) = lookup b gm2<br />
insert (Left a) v (GMapEither gm1 gm2) = GMapEither (insert a v gm1) gm2<br />
insert (Right a) v (GMapEither gm1 gm2) = GMapEither gm1 (insert a v gm2)<br />
</haskell><br />
If you find this code algorithmically surprising, I'd suggest to have a look at [http://www.informatik.uni-bonn.de/~ralf/publications.html#J4 Ralf Hinze's paper]. The only novelty concerning associated types, in these two instances, is that the instances have a context <hask>(GMapKey a, GMapKey b)</hask>. Consequently, the right hand sides of the associated type declarations can use <hask>GMap</hask> recursively at the key types <hask>a</hask> and <hask>b</hask> - not unlike the method definitions use the class methods recursively at the types for which the class is given in the instance context.<br />
<br />
=== Using a generic map ===<br />
<br />
Finally, some code building and quering a generic map:<br />
<haskell><br />
myGMap :: GMap (Int, Either Char ()) String<br />
myGMap = insert (5, Left 'c') "(5, Left 'c')" $<br />
insert (4, Right ()) "(4, Right ())" $<br />
insert (5, Right ()) "This is the one!" $<br />
insert (5, Right ()) "This is the two!" $<br />
insert (6, Right ()) "(6, Right ())" $<br />
insert (5, Left 'a') "(5, Left 'a')" $<br />
empty<br />
main = putStrLn $ maybe "Couldn't find key!" id $ lookup (5, Right ()) myGMap<br />
</haskell><br />
<br />
=== Download the code ===<br />
<br />
If you want to play with this example without copying it off the wiki, just download the [http://darcs.haskell.org/testsuite/tests/ghc-regress/indexed-types/should_run/GMapAssoc.hs source code for <hask>GMap</hask>] from GHC's test suite.<br />
<br />
== Definition of the type system extension ==<br />
<br />
['''NB:''' The following material will eventually become documentation for type families in the GHC User Manual. Please help to improve it by forwarding suggestions to <tt>chak@cse.unsw.edu.au</tt>.]<br />
<br />
Data families appear in two flavours: (1) they can be defined on the toplevel or (2) they can appear inside type classes (in which case they are known as associated types). The former is the more general variant, as it lacks the requirement for the type-indexes to coincide with the class parameters. However, the later can lead to more clearly structured code and compiler warnings if some type instances were - possibly accidentally - omitted. In the following, we always discuss the general toplevel form first and then cover the additional constraints placed on associated types.<br />
<br />
=== Family declarations ===<br />
<br />
Indexed data families are introduced by a signature, such as <br />
<haskell><br />
data family GMap k :: * -> *<br />
</haskell><br />
The special <hask>family</hask> distinguishes family from standard data declarations. The result kind annotation is optional and, as usual, defaults to <hask>*</hask> if omitted. An example is<br />
<haskell><br />
data family Array e<br />
</haskell><br />
Named arguments can also be given explicit kind signatures if needed. Just as with [http://www.haskell.org/ghc/docs/latest/html/users_guide/gadt.html GADT declarations] named arguments are entirely optional, so that we can declare <hask>Array</hask> alternatively with<br />
<haskell><br />
data family Array :: * -> *<br />
</haskell><br />
<br />
==== Associated family declarations ====<br />
<br />
When a data family is declared as part of a type class, we drop the <hask>family</hask> special. The <hask>GMap</hask> declaration takes the following form<br />
<haskell><br />
class GMapKey k where<br />
data GMap k :: * -> *<br />
...<br />
</haskell><br />
In contrast to toplevel declarations, named arguments must be used for all type parameters that are to be used as type-indexes. Moreover, the argument names must be class parameters. Each class parameter may only be used at most once per associated type, but some may be omitted and they may be in an order other than in the class head. Hence, the following contrieved example is admissible:<br />
<haskell><br />
class C a b c where<br />
data T c a :: *<br />
</haskell><br />
If kind signatures are required for argument variables, they need to be given in the class head.<br />
<br />
=== Instance declarations ===<br />
<br />
Instance declarations of data and newtype families are very similar to standard data and newtype declarations. The only two differences are that the keyword <hask>data</hask> or <hask>newtype</hask> is followed by <hask>instance</hask> and that some or all of the type arguments can be non-variable types. For example, the <hask>Either</hask> instance for <hask>GMap</hask> is<br />
<haskell><br />
data instance GMap (Either a b) v = GMapEither (GMap a v) (GMap b v)<br />
</haskell><br />
In this example, the declaration has only one variant. In general, it can be be any number.<br />
<br />
Data and newtype instance declarations are only legit when an appropriate family declaration is in scope - just like class instances require the class declaration to be visible. Moreover, each instance declaration has to conform to the kind determined by its family declaration. This implies that the number of parameters of an instance declaration matches the arity determined by the kind of the family. Although, all data families are declared with the <hask>data</hask> keyword, instances can be either <hask>data</hask> or <hask>newtype</hask>s, or a mix of both.<br />
<br />
Even if type families are defined as toplevel declarations, functions that perform different computations for different family instances still need to be defined as methods of type classes. In particular, the following is not possible:<br />
<haskell><br />
data family T a<br />
data instance T Int = A<br />
data instance T Char = B<br />
nonsence :: T a -> Int<br />
nonsence A = 1 -- WRONG: These two equations together...<br />
nonsence B = 2 -- ...will produce a type error.<br />
</haskell><br />
Given the functionality provided by GADTs (Generalised Algebraic Data Types), it might seem as if a definition, such as the above, should be feasible. However, type families are - in contrast to GADTs - are ''open''; i.e., new instances can always be added, possibly in other modules. Supporting pattern matching across different data instances would require a form of extensible case construct.<br />
<br />
==== Associated type instances ====<br />
<br />
When an associated family instance is declared within a type class instance, we drop the <hask>instance</hask> keyword in the family instance. So, the <hask>Either</hask> instance for <hask>GMap</hask> becomes:<br />
<haskell><br />
instance (GMapKey a, GMapKey b) => GMapKey (Either a b) where<br />
data GMap (Either a b) v = GMapEither (GMap a v) (GMap b v<br />
...<br />
</haskell><br />
The most important point about associated family instances is that the type indexes corresponding to class parameters must be identical to the type given in the instance head; here this is first argument of <hask>GMap</hask>, namely <hask>Either a b</hask>, which coincides with the only class parameter. Any parameters to the family constructor that do not correspond to class parameters, need to be variables in every instance; here this is the variable <hask>v</hask>.<br />
<br />
Instances for an associated family can only appear as part of instances declarations of the class in which the family was declared - just as with the equations of the methods of a class. Also in correspondence to how methods are handled, declarations of associated types can be omitted in class instances. If an associated family instance is omitted, the corresponding instance type is not inhabited; i.e., only diverging expressions, such as <hask>undefined</hask>, can assume the type.<br />
<br />
==== Class instances of type instances ====<br />
<br />
Type class instances of instances of data families can be defined as usual, and in particular data instance declarations can have <hask>deriving</hask> clauses. For example, we can write<br />
<haskell><br />
data GMap () v = GMapUnit (Maybe v)<br />
deriving Show<br />
</haskell><br />
which implcitly defines an instance of the form<br />
<haskell><br />
instance Show v => Show (GMap () v) where ...<br />
</haskell><br />
<br />
Note that class instances are always for particular ''instances'' of a data family and never for an entire family as a whole. This for essentially the same reasons that we cannot define a toplevel function that performs pattern matching on the data constructors of ''different'' instances of a single type family. It would require a form of extensible case construct.<br />
<br />
==== Overlap ====<br />
<br />
The instance declarations of a data family used in a single program may not overlap at all, independent of whether they are associated or not. In contrast to type class instances, this is not only a matter of consistency, but one of type safety.<br />
<br />
=== Import and export ===<br />
<br />
The association of data constructors with type families is more dynamic than that is the case with standard data and newtype declarations. In the standard case, the notation <hask>T(..)</hask> in an import or export list denotes the type constructor and all the data constructors introduced in its declaration. However, a family declaration never introduces any data constructors; instead, data constructors are introduced by family instances. As a result, which data constructors are associated with a type family depends on the currently visible instance declarations for that family. Consequently, an import or export item of the form <hask>T(..)</hask> denotes the family constructor and all currently visible data constructors - in the case of an export item, these may be either imported or defined in the current module. The treatment of import and export items that explicitly list data constructors, such as <hask>GMap(GMapEither)</hask>, is analogous.<br />
<br />
==== Associated families ====<br />
<br />
As expected, an import or export item of the form <hask>C(..)</hask> denotes all of the class' methods and associated types. However, when associated types are explicitly listed as subitems of a class, we need some new syntax, as uppercase identifiers as subitems are usually data constructors, not type constructors. To clarify that we denote types here, each associated type name needs to be prefixed by the keyword <hask>type</hask>. So for example, when explicitly listing the components of the <hask>GMapKey</hask> class, we write <hask>GMapKey(type GMap, empty, lookup, insert)</hask>.<br />
<br />
==== Examples ====<br />
<br />
Assuming our running <hask>GMapKey</hask> class example, let us look at some export lists and their meaning:<br />
<br />
* <hask>module GMap (GMapKey) where...</hask>: Exports just the class name.<br />
* <hask>module GMap (GMapKey(..)) where...</hask>: Exports the class, the associated type <hask>GMap</hask> and the member functions <hask>empty</hask>, <hask>lookup</hask>, and <hask>insert</hask>. None of the data constructors is exported.<br />
* <hask>module GMap (GMapKey(..), GMap(..)) where...</hask>: As before, but also exports all the data constructors <hask>GMapInt</hask>, <hask>GMapChar</hask>, <hask>GMapUnit</hask>, <hask>GMapPair</hask>, and <hask>GMapUnit</hask>.<br />
* <hask>module GMap (GMapKey(empty, lookup, insert), GMap(..)) where...</hask>: As before.<br />
* <hask>module GMap (GMapKey, empty, lookup, insert, GMap(..)) where...</hask>: As before.<br />
<br />
Finally, you can write <hask>GMapKey(type GMap)</hask> to denote both the class <hask>GMapKey</hask> as well as its associated type <hask>GMap</hask>. However, you cannot write <hask>GMapKey(type GMap(..))</hask> &mdash; i.e., sub-component specifications cannot be nested. To specify <hask>GMap</hask>'s data constructors, you have to list it separately.<br />
<br />
==== Instances ====<br />
<br />
Family instances are implicitly exported, just like class instances. However, this applies only to the heads of instances, not to the data constructors an instance defines.<br />
<br />
<br />
== A associated type synonym example ==<br />
<br />
Associated data types ar much better behaved than<br />
functional dependencies. Hence, GHC's type checking and inference are<br />
more powerful. Here is an example of how to port your existing functional <br />
depenency programs to associated type synonyms.<br />
<br />
=== The <hask>class</hask> declaration ===<br />
<br />
Here's an example from the original Functional Dependencies paper:<br />
<haskell><br />
class Collects e ce | ce -> e where<br />
empty :: ce<br />
insert :: e -> ce -> ce<br />
member :: e -> ce -> Bool<br />
toList :: ce -> [e]<br />
</haskell><br />
<br />
With associated type synonyms we can write this as:<br />
<haskell><br />
class Collects ce where<br />
type Elem ce<br />
empty :: ce<br />
insert :: Elem ce -> ce -> ce<br />
member :: Elem ce -> ce -> Bool<br />
toList :: ce -> [Elem ce]<br />
</haskell><br />
That's right, we have dropped from a multi-paramter type class<br />
to a single parameter type class. The parameter <hask>e</hask><br />
has become an associated type <hask>Elem ce</hask>.<br />
<br />
=== An <hask>instance</hask>===<br />
<br />
Here's an instance, with functional dependencies:<br />
<haskell><br />
instance Eq e => Collects e [e] where<br />
empty = []<br />
insert e l = (e:l)<br />
member e [] = False<br />
member e (x:xs) | e == x = True<br />
| otherwise = member e xs<br />
toList l = l<br />
</haskell><br />
<br />
With associated type synonyms, this becomes:<br />
<haskell><br />
instance Eq e => Collects [e] where<br />
type Elem [e] = e<br />
empty = []<br />
insert e l = (e:l)<br />
member e [] = False<br />
member e (x:xs) | e == x = True<br />
| otherwise = member e xs<br />
toList l = l<br />
</haskell><br />
<br />
=== Using generic collections ===<br />
<br />
With Functional Dependencies the code would be:<br />
<haskell><br />
sumCollects :: (Collects e c1,Collects e c2) => c1 -> c2 -> c2<br />
sumCollects c1 c2 = foldr insert c2 (toList c1)<br />
</haskell><br />
<br />
In contrast, with associated type synonyms, we get:<br />
<haskell><br />
sumCollects :: (Collects c1,Collects c2,Elem c1 ~ Elem c2) => c1 -> c2 -> c2<br />
sumCollects c1 c2 = foldr insert c2 (toList c1)<br />
</haskell><br />
<br />
<br />
== Definition of the type system extension ==<br />
<br />
['''NB:''' The following material will eventually become documentation for type families in the GHC User Manual. Please help to improve it by forwarding suggestions to <tt>tom.schrijvers@cs.kuleuven.be</tt>.]<br />
<br />
Type families appear in two flavours: (1) they can be defined on the toplevel or (2) they can appear inside type classes (in which case they are known as associated type synonyms). The former is the more general variant, as it lacks the requirement for the type-indexes to coincide with the class parameters. However, the later can lead to more clearly structured code and compiler warnings if some type instances were - possibly accidentally - omitted. In the following, we always discuss the general toplevel form first and then cover the additional constraints placed on associated types.<br />
<br />
=== Family declarations ===<br />
<br />
Indexed type families are introduced by a signature, such as <br />
<haskell><br />
type family Elem c :: *<br />
</haskell><br />
The special <hask>family</hask> distinguishes family from standard type declarations. The result kind annotation is optional and, as usual, defaults to <hask>*</hask> if omitted. An example is<br />
<haskell><br />
type family Elem c<br />
</haskell><br />
Named arguments can also be given explicit kind signatures if needed. Named arguments are _not_ optional.<br />
<br />
<br />
== Open issues ==<br />
<br />
<br />
None.</div>Tschrijvershttps://wiki.haskell.org/index.php?title=GHC/Type_families&diff=13217GHC/Type families2007-05-25T08:32:22Z<p>Tschrijvers: </p>
<hr />
<div>[[Category:GHC|Indexed types]]<br />
== Data and type families in GHC ==<br />
<br />
Data and type families are a new addition to GHC's type extensions. They are currently an '''experimental''' feature and so their design may still change to some degree. The current implementation covers ''data families'' (including newtypes), which can either be on the toplevel or inside class declarations - the latter are also known as [http://www.cse.unsw.edu.au/~chak/papers/CKPM05.html associated data types]. <br />
<br />
'''NB:''' Please note that type families (and hence also associated type synonyms) are '''not''' fully implemented yet. Any attempt to use them will lead to strange error messages. For the moment, you can only use <hask>data</hask> families.<br />
<br />
== What do I need to use data families? ==<br />
<br />
Indexed type families are implemented in GHC's HEAD (from version 6.7), which you can obtain in binary form from the [http://www.haskell.org/ghc/dist/current/dist/ nightly snapshots] or in source form from the [http://hackage.haskell.org/trac/ghc/wiki/Building/GettingTheSources source repository]. To enable indexed type families in GHC 6.7, you need to supply the compiler option <tt>-ftype-families</tt> (or <tt>-fglasgow-exts</tt>, which implies it). NB: The option used to be called <tt>-findexed-types</tt> for a while.<br />
<br />
== An associated data type example ==<br />
<br />
As an example, consider Ralf Hinze's [http://www.informatik.uni-bonn.de/~ralf/publications.html#J4 generalised tries], a form of generic finite maps. <br />
<br />
=== The class declaration ===<br />
<br />
We define a type class whose instances are the types that we can use as keys in our generic maps:<br />
<haskell><br />
class GMapKey k where<br />
data GMap k :: * -> *<br />
empty :: GMap k v<br />
lookup :: k -> GMap k v -> Maybe v<br />
insert :: k -> v -> GMap k v -> GMap k v<br />
</haskell><br />
The interesting part is the ''associated data family'' declaration of the class. It gives a [http://www.haskell.org/ghc/docs/latest/html/users_guide/type-extensions.html#sec-kinding ''kind signature''] (here <hask>* -> *</hask>) for the associated data type <hask>GMap k</hask> - analog to how methods receive a type signature in a class declaration.<br />
<br />
What it is important to notice is that the first parameter of the associated type <hask>GMap</hask> coincides with the class parameter of <hask>GMapKey</hask>. This indicates that also in all instances of the class, the instances of the associated data type need to have their first argument match up with the instance type. In general, the type arguments of an associated type can be a subset of the class parameters (in a multi-parameter type class) and they can appear in any order, possibly in an order other than in the class head. The latter can be useful if the associated data type is partially applied in some contexts.<br />
<br />
The second important point is that as <hask>GMap k</hask> has kind <hask>* -> *</hask> and <hask>k</hask> (implicitly) has kind <hask>*</hask>, the type constructor <hask>GMap</hask> (without an argument) has kind <hask>* -> * -> *</hask>. Consequently, we see that <hask>GMap</hask> is applied to two arguments in the signatures of the methods <hask>empty</hask>, <hask>lookup</hask>, and <hask>insert</hask>.<br />
<br />
=== An Int instance ===<br />
<br />
To use Ints as keys into generic maps, we declare an instance that simply uses <hask>Data.Map</hask>, thusly:<br />
<haskell><br />
instance GMapKey Int where<br />
data GMap Int v = GMapInt (Data.Map.Map Int v)<br />
empty = GMapInt Data.Map.empty<br />
lookup k (GMapInt m) = Data.Map.lookup k m<br />
insert k v (GMapInt m) = GMapInt (Data.Map.insert k v m)<br />
</haskell><br />
The <hask>Int</hask> instance of the associated data type <hask>GMap</hask> needs to have both of its parameters, but as only the first one corresponds to a class parameter, the second needs to be a type variable (here <hask>v</hask>). As mentioned before any associated type parameter that corresponds to a class parameter must be identical to the class parameter in each instance. The right hand side of the associated data declaration is like that of any other data type.<br />
<br />
NB: At the moment, GADT syntax is not allowed for associated data types (or other indexed types). This is not a fundemental limitation, but just a shortcoming of the current implementation, which we expect to lift in the future.<br />
<br />
As an exercise, implement an instance for <hask>Char</hask> that maps back to the <hask>Int</hask> instance using the conversion functions <hask>Char.ord</hask> and <hask>Char.chr</hask>.<br />
<br />
=== A unit instance ===<br />
<br />
Generic definitions, apart from elementary types, typically cover units, products, and sums. We start here with the unit instance for <hask>GMap</hask>:<br />
<haskell><br />
instance GMapKey () where<br />
data GMap () v = GMapUnit (Maybe v)<br />
empty = GMapUnit Nothing<br />
lookup () (GMapUnit v) = v<br />
insert () v (GMapUnit _) = GMapUnit $ Just v<br />
</haskell><br />
For unit, the map is just a <hask>Maybe</hask> value.<br />
<br />
=== Product and sum instances ===<br />
<br />
Nest, let us define the instances for pairs and sums (i.e., <hask>Either</hask>):<br />
<haskell><br />
instance (GMapKey a, GMapKey b) => GMapKey (a, b) where<br />
data GMap (a, b) v = GMapPair (GMap a (GMap b v))<br />
empty = GMapPair empty<br />
lookup (a, b) (GMapPair gm) = lookup a gm >>= lookup b <br />
insert (a, b) v (GMapPair gm) = GMapPair $ case lookup a gm of<br />
Nothing -> insert a (insert b v empty) gm<br />
Just gm2 -> insert a (insert b v gm2 ) gm<br />
<br />
instance (GMapKey a, GMapKey b) => GMapKey (Either a b) where<br />
data GMap (Either a b) v = GMapEither (GMap a v) (GMap b v)<br />
empty = GMapEither empty empty<br />
lookup (Left a) (GMapEither gm1 _gm2) = lookup a gm1<br />
lookup (Right b) (GMapEither _gm1 gm2 ) = lookup b gm2<br />
insert (Left a) v (GMapEither gm1 gm2) = GMapEither (insert a v gm1) gm2<br />
insert (Right a) v (GMapEither gm1 gm2) = GMapEither gm1 (insert a v gm2)<br />
</haskell><br />
If you find this code algorithmically surprising, I'd suggest to have a look at [http://www.informatik.uni-bonn.de/~ralf/publications.html#J4 Ralf Hinze's paper]. The only novelty concerning associated types, in these two instances, is that the instances have a context <hask>(GMapKey a, GMapKey b)</hask>. Consequently, the right hand sides of the associated type declarations can use <hask>GMap</hask> recursively at the key types <hask>a</hask> and <hask>b</hask> - not unlike the method definitions use the class methods recursively at the types for which the class is given in the instance context.<br />
<br />
=== Using a generic map ===<br />
<br />
Finally, some code building and quering a generic map:<br />
<haskell><br />
myGMap :: GMap (Int, Either Char ()) String<br />
myGMap = insert (5, Left 'c') "(5, Left 'c')" $<br />
insert (4, Right ()) "(4, Right ())" $<br />
insert (5, Right ()) "This is the one!" $<br />
insert (5, Right ()) "This is the two!" $<br />
insert (6, Right ()) "(6, Right ())" $<br />
insert (5, Left 'a') "(5, Left 'a')" $<br />
empty<br />
main = putStrLn $ maybe "Couldn't find key!" id $ lookup (5, Right ()) myGMap<br />
</haskell><br />
<br />
=== Download the code ===<br />
<br />
If you want to play with this example without copying it off the wiki, just download the [http://darcs.haskell.org/testsuite/tests/ghc-regress/indexed-types/should_run/GMapAssoc.hs source code for <hask>GMap</hask>] from GHC's test suite.<br />
<br />
== Definition of the type system extension ==<br />
<br />
['''NB:''' The following material will eventually become documentation for type families in the GHC User Manual. Please help to improve it by forwarding suggestions to <tt>chak@cse.unsw.edu.au</tt>.]<br />
<br />
Data families appear in two flavours: (1) they can be defined on the toplevel or (2) they can appear inside type classes (in which case they are known as associated types). The former is the more general variant, as it lacks the requirement for the type-indexes to coincide with the class parameters. However, the later can lead to more clearly structured code and compiler warnings if some type instances were - possibly accidentally - omitted. In the following, we always discuss the general toplevel form first and then cover the additional constraints placed on associated types.<br />
<br />
=== Family declarations ===<br />
<br />
Indexed data families are introduced by a signature, such as <br />
<haskell><br />
data family GMap k :: * -> *<br />
</haskell><br />
The special <hask>family</hask> distinguishes family from standard data declarations. The result kind annotation is optional and, as usual, defaults to <hask>*</hask> if omitted. An example is<br />
<haskell><br />
data family Array e<br />
</haskell><br />
Named arguments can also be given explicit kind signatures if needed. Just as with [http://www.haskell.org/ghc/docs/latest/html/users_guide/gadt.html GADT declarations] named arguments are entirely optional, so that we can declare <hask>Array</hask> alternatively with<br />
<haskell><br />
data family Array :: * -> *<br />
</haskell><br />
<br />
==== Associated family declarations ====<br />
<br />
When a data family is declared as part of a type class, we drop the <hask>family</hask> special. The <hask>GMap</hask> declaration takes the following form<br />
<haskell><br />
class GMapKey k where<br />
data GMap k :: * -> *<br />
...<br />
</haskell><br />
In contrast to toplevel declarations, named arguments must be used for all type parameters that are to be used as type-indexes. Moreover, the argument names must be class parameters. Each class parameter may only be used at most once per associated type, but some may be omitted and they may be in an order other than in the class head. Hence, the following contrieved example is admissible:<br />
<haskell><br />
class C a b c where<br />
data T c a :: *<br />
</haskell><br />
If kind signatures are required for argument variables, they need to be given in the class head.<br />
<br />
=== Instance declarations ===<br />
<br />
Instance declarations of data and newtype families are very similar to standard data and newtype declarations. The only two differences are that the keyword <hask>data</hask> or <hask>newtype</hask> is followed by <hask>instance</hask> and that some or all of the type arguments can be non-variable types. For example, the <hask>Either</hask> instance for <hask>GMap</hask> is<br />
<haskell><br />
data instance GMap (Either a b) v = GMapEither (GMap a v) (GMap b v)<br />
</haskell><br />
In this example, the declaration has only one variant. In general, it can be be any number.<br />
<br />
Data and newtype instance declarations are only legit when an appropriate family declaration is in scope - just like class instances require the class declaration to be visible. Moreover, each instance declaration has to conform to the kind determined by its family declaration. This implies that the number of parameters of an instance declaration matches the arity determined by the kind of the family. Although, all data families are declared with the <hask>data</hask> keyword, instances can be either <hask>data</hask> or <hask>newtype</hask>s, or a mix of both.<br />
<br />
Even if type families are defined as toplevel declarations, functions that perform different computations for different family instances still need to be defined as methods of type classes. In particular, the following is not possible:<br />
<haskell><br />
data family T a<br />
data instance T Int = A<br />
data instance T Char = B<br />
nonsence :: T a -> Int<br />
nonsence A = 1 -- WRONG: These two equations together...<br />
nonsence B = 2 -- ...will produce a type error.<br />
</haskell><br />
Given the functionality provided by GADTs (Generalised Algebraic Data Types), it might seem as if a definition, such as the above, should be feasible. However, type families are - in contrast to GADTs - are ''open''; i.e., new instances can always be added, possibly in other modules. Supporting pattern matching across different data instances would require a form of extensible case construct.<br />
<br />
==== Associated type instances ====<br />
<br />
When an associated family instance is declared within a type class instance, we drop the <hask>instance</hask> keyword in the family instance. So, the <hask>Either</hask> instance for <hask>GMap</hask> becomes:<br />
<haskell><br />
instance (GMapKey a, GMapKey b) => GMapKey (Either a b) where<br />
data GMap (Either a b) v = GMapEither (GMap a v) (GMap b v<br />
...<br />
</haskell><br />
The most important point about associated family instances is that the type indexes corresponding to class parameters must be identical to the type given in the instance head; here this is first argument of <hask>GMap</hask>, namely <hask>Either a b</hask>, which coincides with the only class parameter. Any parameters to the family constructor that do not correspond to class parameters, need to be variables in every instance; here this is the variable <hask>v</hask>.<br />
<br />
Instances for an associated family can only appear as part of instances declarations of the class in which the family was declared - just as with the equations of the methods of a class. Also in correspondence to how methods are handled, declarations of associated types can be omitted in class instances. If an associated family instance is omitted, the corresponding instance type is not inhabited; i.e., only diverging expressions, such as <hask>undefined</hask>, can assume the type.<br />
<br />
==== Class instances of type instances ====<br />
<br />
Type class instances of instances of data families can be defined as usual, and in particular data instance declarations can have <hask>deriving</hask> clauses. For example, we can write<br />
<haskell><br />
data GMap () v = GMapUnit (Maybe v)<br />
deriving Show<br />
</haskell><br />
which implcitly defines an instance of the form<br />
<haskell><br />
instance Show v => Show (GMap () v) where ...<br />
</haskell><br />
<br />
Note that class instances are always for particular ''instances'' of a data family and never for an entire family as a whole. This for essentially the same reasons that we cannot define a toplevel function that performs pattern matching on the data constructors of ''different'' instances of a single type family. It would require a form of extensible case construct.<br />
<br />
==== Overlap ====<br />
<br />
The instance declarations of a data family used in a single program may not overlap at all, independent of whether they are associated or not. In contrast to type class instances, this is not only a matter of consistency, but one of type safety.<br />
<br />
=== Import and export ===<br />
<br />
The association of data constructors with type families is more dynamic than that is the case with standard data and newtype declarations. In the standard case, the notation <hask>T(..)</hask> in an import or export list denotes the type constructor and all the data constructors introduced in its declaration. However, a family declaration never introduces any data constructors; instead, data constructors are introduced by family instances. As a result, which data constructors are associated with a type family depends on the currently visible instance declarations for that family. Consequently, an import or export item of the form <hask>T(..)</hask> denotes the family constructor and all currently visible data constructors - in the case of an export item, these may be either imported or defined in the current module. The treatment of import and export items that explicitly list data constructors, such as <hask>GMap(GMapEither)</hask>, is analogous.<br />
<br />
==== Associated families ====<br />
<br />
As expected, an import or export item of the form <hask>C(..)</hask> denotes all of the class' methods and associated types. However, when associated types are explicitly listed as subitems of a class, we need some new syntax, as uppercase identifiers as subitems are usually data constructors, not type constructors. To clarify that we denote types here, each associated type name needs to be prefixed by the keyword <hask>type</hask>. So for example, when explicitly listing the components of the <hask>GMapKey</hask> class, we write <hask>GMapKey(type GMap, empty, lookup, insert)</hask>.<br />
<br />
==== Examples ====<br />
<br />
Assuming our running <hask>GMapKey</hask> class example, let us look at some export lists and their meaning:<br />
<br />
* <hask>module GMap (GMapKey) where...</hask>: Exports just the class name.<br />
* <hask>module GMap (GMapKey(..)) where...</hask>: Exports the class, the associated type <hask>GMap</hask> and the member functions <hask>empty</hask>, <hask>lookup</hask>, and <hask>insert</hask>. None of the data constructors is exported.<br />
* <hask>module GMap (GMapKey(..), GMap(..)) where...</hask>: As before, but also exports all the data constructors <hask>GMapInt</hask>, <hask>GMapChar</hask>, <hask>GMapUnit</hask>, <hask>GMapPair</hask>, and <hask>GMapUnit</hask>.<br />
* <hask>module GMap (GMapKey(empty, lookup, insert), GMap(..)) where...</hask>: As before.<br />
* <hask>module GMap (GMapKey, empty, lookup, insert, GMap(..)) where...</hask>: As before.<br />
<br />
Finally, you can write <hask>GMapKey(type GMap)</hask> to denote both the class <hask>GMapKey</hask> as well as its associated type <hask>GMap</hask>. However, you cannot write <hask>GMapKey(type GMap(..))</hask> &mdash; i.e., sub-component specifications cannot be nested. To specify <hask>GMap</hask>'s data constructors, you have to list it separately.<br />
<br />
==== Instances ====<br />
<br />
Family instances are implicitly exported, just like class instances. However, this applies only to the heads of instances, not to the data constructors an instance defines.<br />
<br />
<br />
== A associated type synonym example ==<br />
<br />
Associated data types ar much better behaved than<br />
functional dependencies. Hence, GHC's type checking and inference are<br />
more powerful. Here is an example of how to port your existing functional <br />
depenency programs to associated type synonyms.<br />
<br />
=== The <hask>class</hask> declaration ===<br />
<br />
Here's an example from the original Functional Dependencies paper:<br />
<haskell><br />
class Collects e ce | ce -> e where<br />
empty :: ce<br />
insert :: e -> ce -> ce<br />
member :: e -> ce -> Bool<br />
toList :: ce -> [e]<br />
</haskell><br />
<br />
With associated type synonyms we can write this as:<br />
<haskell><br />
class Collects ce where<br />
type Elem ce<br />
empty :: ce<br />
insert :: Elem ce -> ce -> ce<br />
member :: Elem ce -> ce -> Bool<br />
toList :: ce -> [Elem ce]<br />
</haskell><br />
That's right, we have dropped from a multi-paramter type class<br />
to a single parameter type class. The parameter <hask>e</hask><br />
has become an associated type <hask>Elem ce</hask>.<br />
<br />
=== An <hask>instance</hask>===<br />
<br />
Here's an instance, with functional dependencies:<br />
<haskell><br />
instance Eq e => Collects e [e] where<br />
empty = []<br />
insert e l = (e:l)<br />
member e [] = False<br />
member e (x:xs) | e == x = True<br />
| otherwise = member e xs<br />
toList l = l<br />
</haskell><br />
<br />
With associated type synonyms, this becomes:<br />
<haskell><br />
instance Eq e => Collects [e] where<br />
type Elem [e] = e<br />
empty = []<br />
insert e l = (e:l)<br />
member e [] = False<br />
member e (x:xs) | e == x = True<br />
| otherwise = member e xs<br />
toList l = l<br />
</haskell><br />
<br />
=== Using generic collections ===<br />
<br />
With Functional Dependencies the code would be:<br />
<haskell><br />
sumCollects :: (Collects e c1,Collects e c2) => c1 -> c2 -> c2<br />
sumCollects c1 c2 = foldr insert c2 (toList c1)<br />
</haskell><br />
<br />
In contrast, with associated type synonyms, we get:<br />
<haskell><br />
sumCollects :: (Collects c1,Collects c2,Elem c1 ~ Elem c2) => c1 -> c2 -> c2<br />
sumCollects c1 c2 = foldr insert c2 (toList c1)<br />
</haskell><br />
<br />
<br />
== Open issues ==<br />
<br />
<br />
None.</div>Tschrijvershttps://wiki.haskell.org/index.php?title=GHC/Type_families&diff=13216GHC/Type families2007-05-25T08:24:26Z<p>Tschrijvers: </p>
<hr />
<div>[[Category:GHC|Indexed types]]<br />
== Data and type families in GHC ==<br />
<br />
Data and type families are a new addition to GHC's type extensions. They are currently an '''experimental''' feature and so their design may still change to some degree. The current implementation covers ''data families'' (including newtypes), which can either be on the toplevel or inside class declarations - the latter are also known as [http://www.cse.unsw.edu.au/~chak/papers/CKPM05.html associated data types]. <br />
<br />
'''NB:''' Please note that type families (and hence also associated type synonyms) are '''not''' fully implemented yet. Any attempt to use them will lead to strange error messages. For the moment, you can only use <hask>data</hask> families.<br />
<br />
== What do I need to use data families? ==<br />
<br />
Indexed type families are implemented in GHC's HEAD (from version 6.7), which you can obtain in binary form from the [http://www.haskell.org/ghc/dist/current/dist/ nightly snapshots] or in source form from the [http://hackage.haskell.org/trac/ghc/wiki/Building/GettingTheSources source repository]. To enable indexed type families in GHC 6.7, you need to supply the compiler option <tt>-ftype-families</tt> (or <tt>-fglasgow-exts</tt>, which implies it). NB: The option used to be called <tt>-findexed-types</tt> for a while.<br />
<br />
== An associated data type example ==<br />
<br />
As an example, consider Ralf Hinze's [http://www.informatik.uni-bonn.de/~ralf/publications.html#J4 generalised tries], a form of generic finite maps. <br />
<br />
=== The class declaration ===<br />
<br />
We define a type class whose instances are the types that we can use as keys in our generic maps:<br />
<haskell><br />
class GMapKey k where<br />
data GMap k :: * -> *<br />
empty :: GMap k v<br />
lookup :: k -> GMap k v -> Maybe v<br />
insert :: k -> v -> GMap k v -> GMap k v<br />
</haskell><br />
The interesting part is the ''associated data family'' declaration of the class. It gives a [http://www.haskell.org/ghc/docs/latest/html/users_guide/type-extensions.html#sec-kinding ''kind signature''] (here <hask>* -> *</hask>) for the associated data type <hask>GMap k</hask> - analog to how methods receive a type signature in a class declaration.<br />
<br />
What it is important to notice is that the first parameter of the associated type <hask>GMap</hask> coincides with the class parameter of <hask>GMapKey</hask>. This indicates that also in all instances of the class, the instances of the associated data type need to have their first argument match up with the instance type. In general, the type arguments of an associated type can be a subset of the class parameters (in a multi-parameter type class) and they can appear in any order, possibly in an order other than in the class head. The latter can be useful if the associated data type is partially applied in some contexts.<br />
<br />
The second important point is that as <hask>GMap k</hask> has kind <hask>* -> *</hask> and <hask>k</hask> (implicitly) has kind <hask>*</hask>, the type constructor <hask>GMap</hask> (without an argument) has kind <hask>* -> * -> *</hask>. Consequently, we see that <hask>GMap</hask> is applied to two arguments in the signatures of the methods <hask>empty</hask>, <hask>lookup</hask>, and <hask>insert</hask>.<br />
<br />
=== An Int instance ===<br />
<br />
To use Ints as keys into generic maps, we declare an instance that simply uses <hask>Data.Map</hask>, thusly:<br />
<haskell><br />
instance GMapKey Int where<br />
data GMap Int v = GMapInt (Data.Map.Map Int v)<br />
empty = GMapInt Data.Map.empty<br />
lookup k (GMapInt m) = Data.Map.lookup k m<br />
insert k v (GMapInt m) = GMapInt (Data.Map.insert k v m)<br />
</haskell><br />
The <hask>Int</hask> instance of the associated data type <hask>GMap</hask> needs to have both of its parameters, but as only the first one corresponds to a class parameter, the second needs to be a type variable (here <hask>v</hask>). As mentioned before any associated type parameter that corresponds to a class parameter must be identical to the class parameter in each instance. The right hand side of the associated data declaration is like that of any other data type.<br />
<br />
NB: At the moment, GADT syntax is not allowed for associated data types (or other indexed types). This is not a fundemental limitation, but just a shortcoming of the current implementation, which we expect to lift in the future.<br />
<br />
As an exercise, implement an instance for <hask>Char</hask> that maps back to the <hask>Int</hask> instance using the conversion functions <hask>Char.ord</hask> and <hask>Char.chr</hask>.<br />
<br />
=== A unit instance ===<br />
<br />
Generic definitions, apart from elementary types, typically cover units, products, and sums. We start here with the unit instance for <hask>GMap</hask>:<br />
<haskell><br />
instance GMapKey () where<br />
data GMap () v = GMapUnit (Maybe v)<br />
empty = GMapUnit Nothing<br />
lookup () (GMapUnit v) = v<br />
insert () v (GMapUnit _) = GMapUnit $ Just v<br />
</haskell><br />
For unit, the map is just a <hask>Maybe</hask> value.<br />
<br />
=== Product and sum instances ===<br />
<br />
Nest, let us define the instances for pairs and sums (i.e., <hask>Either</hask>):<br />
<haskell><br />
instance (GMapKey a, GMapKey b) => GMapKey (a, b) where<br />
data GMap (a, b) v = GMapPair (GMap a (GMap b v))<br />
empty = GMapPair empty<br />
lookup (a, b) (GMapPair gm) = lookup a gm >>= lookup b <br />
insert (a, b) v (GMapPair gm) = GMapPair $ case lookup a gm of<br />
Nothing -> insert a (insert b v empty) gm<br />
Just gm2 -> insert a (insert b v gm2 ) gm<br />
<br />
instance (GMapKey a, GMapKey b) => GMapKey (Either a b) where<br />
data GMap (Either a b) v = GMapEither (GMap a v) (GMap b v)<br />
empty = GMapEither empty empty<br />
lookup (Left a) (GMapEither gm1 _gm2) = lookup a gm1<br />
lookup (Right b) (GMapEither _gm1 gm2 ) = lookup b gm2<br />
insert (Left a) v (GMapEither gm1 gm2) = GMapEither (insert a v gm1) gm2<br />
insert (Right a) v (GMapEither gm1 gm2) = GMapEither gm1 (insert a v gm2)<br />
</haskell><br />
If you find this code algorithmically surprising, I'd suggest to have a look at [http://www.informatik.uni-bonn.de/~ralf/publications.html#J4 Ralf Hinze's paper]. The only novelty concerning associated types, in these two instances, is that the instances have a context <hask>(GMapKey a, GMapKey b)</hask>. Consequently, the right hand sides of the associated type declarations can use <hask>GMap</hask> recursively at the key types <hask>a</hask> and <hask>b</hask> - not unlike the method definitions use the class methods recursively at the types for which the class is given in the instance context.<br />
<br />
=== Using a generic map ===<br />
<br />
Finally, some code building and quering a generic map:<br />
<haskell><br />
myGMap :: GMap (Int, Either Char ()) String<br />
myGMap = insert (5, Left 'c') "(5, Left 'c')" $<br />
insert (4, Right ()) "(4, Right ())" $<br />
insert (5, Right ()) "This is the one!" $<br />
insert (5, Right ()) "This is the two!" $<br />
insert (6, Right ()) "(6, Right ())" $<br />
insert (5, Left 'a') "(5, Left 'a')" $<br />
empty<br />
main = putStrLn $ maybe "Couldn't find key!" id $ lookup (5, Right ()) myGMap<br />
</haskell><br />
<br />
=== Download the code ===<br />
<br />
If you want to play with this example without copying it off the wiki, just download the [http://darcs.haskell.org/testsuite/tests/ghc-regress/indexed-types/should_run/GMapAssoc.hs source code for <hask>GMap</hask>] from GHC's test suite.<br />
<br />
== Definition of the type system extension ==<br />
<br />
['''NB:''' The following material will eventually become documentation for type families in the GHC User Manual. Please help to improve it by forwarding suggestions to <tt>chak@cse.unsw.edu.au</tt>.]<br />
<br />
Data families appear in two flavours: (1) they can be defined on the toplevel or (2) they can appear inside type classes (in which case they are known as associated types). The former is the more general variant, as it lacks the requirement for the type-indexes to coincide with the class parameters. However, the later can lead to more clearly structured code and compiler warnings if some type instances were - possibly accidentally - omitted. In the following, we always discuss the general toplevel form first and then cover the additional constraints placed on associated types.<br />
<br />
=== Family declarations ===<br />
<br />
Indexed data families are introduced by a signature, such as <br />
<haskell><br />
data family GMap k :: * -> *<br />
</haskell><br />
The special <hask>family</hask> distinguishes family from standard data declarations. The result kind annotation is optional and, as usual, defaults to <hask>*</hask> if omitted. An example is<br />
<haskell><br />
data family Array e<br />
</haskell><br />
Named arguments can also be given explicit kind signatures if needed. Just as with [http://www.haskell.org/ghc/docs/latest/html/users_guide/gadt.html GADT declarations] named arguments are entirely optional, so that we can declare <hask>Array</hask> alternatively with<br />
<haskell><br />
data family Array :: * -> *<br />
</haskell><br />
<br />
==== Associated family declarations ====<br />
<br />
When a data family is declared as part of a type class, we drop the <hask>family</hask> special. The <hask>GMap</hask> declaration takes the following form<br />
<haskell><br />
class GMapKey k where<br />
data GMap k :: * -> *<br />
...<br />
</haskell><br />
In contrast to toplevel declarations, named arguments must be used for all type parameters that are to be used as type-indexes. Moreover, the argument names must be class parameters. Each class parameter may only be used at most once per associated type, but some may be omitted and they may be in an order other than in the class head. Hence, the following contrieved example is admissible:<br />
<haskell><br />
class C a b c where<br />
data T c a :: *<br />
</haskell><br />
If kind signatures are required for argument variables, they need to be given in the class head.<br />
<br />
=== Instance declarations ===<br />
<br />
Instance declarations of data and newtype families are very similar to standard data and newtype declarations. The only two differences are that the keyword <hask>data</hask> or <hask>newtype</hask> is followed by <hask>instance</hask> and that some or all of the type arguments can be non-variable types. For example, the <hask>Either</hask> instance for <hask>GMap</hask> is<br />
<haskell><br />
data instance GMap (Either a b) v = GMapEither (GMap a v) (GMap b v)<br />
</haskell><br />
In this example, the declaration has only one variant. In general, it can be be any number.<br />
<br />
Data and newtype instance declarations are only legit when an appropriate family declaration is in scope - just like class instances require the class declaration to be visible. Moreover, each instance declaration has to conform to the kind determined by its family declaration. This implies that the number of parameters of an instance declaration matches the arity determined by the kind of the family. Although, all data families are declared with the <hask>data</hask> keyword, instances can be either <hask>data</hask> or <hask>newtype</hask>s, or a mix of both.<br />
<br />
Even if type families are defined as toplevel declarations, functions that perform different computations for different family instances still need to be defined as methods of type classes. In particular, the following is not possible:<br />
<haskell><br />
data family T a<br />
data instance T Int = A<br />
data instance T Char = B<br />
nonsence :: T a -> Int<br />
nonsence A = 1 -- WRONG: These two equations together...<br />
nonsence B = 2 -- ...will produce a type error.<br />
</haskell><br />
Given the functionality provided by GADTs (Generalised Algebraic Data Types), it might seem as if a definition, such as the above, should be feasible. However, type families are - in contrast to GADTs - are ''open''; i.e., new instances can always be added, possibly in other modules. Supporting pattern matching across different data instances would require a form of extensible case construct.<br />
<br />
==== Associated type instances ====<br />
<br />
When an associated family instance is declared within a type class instance, we drop the <hask>instance</hask> keyword in the family instance. So, the <hask>Either</hask> instance for <hask>GMap</hask> becomes:<br />
<haskell><br />
instance (GMapKey a, GMapKey b) => GMapKey (Either a b) where<br />
data GMap (Either a b) v = GMapEither (GMap a v) (GMap b v<br />
...<br />
</haskell><br />
The most important point about associated family instances is that the type indexes corresponding to class parameters must be identical to the type given in the instance head; here this is first argument of <hask>GMap</hask>, namely <hask>Either a b</hask>, which coincides with the only class parameter. Any parameters to the family constructor that do not correspond to class parameters, need to be variables in every instance; here this is the variable <hask>v</hask>.<br />
<br />
Instances for an associated family can only appear as part of instances declarations of the class in which the family was declared - just as with the equations of the methods of a class. Also in correspondence to how methods are handled, declarations of associated types can be omitted in class instances. If an associated family instance is omitted, the corresponding instance type is not inhabited; i.e., only diverging expressions, such as <hask>undefined</hask>, can assume the type.<br />
<br />
==== Class instances of type instances ====<br />
<br />
Type class instances of instances of data families can be defined as usual, and in particular data instance declarations can have <hask>deriving</hask> clauses. For example, we can write<br />
<haskell><br />
data GMap () v = GMapUnit (Maybe v)<br />
deriving Show<br />
</haskell><br />
which implcitly defines an instance of the form<br />
<haskell><br />
instance Show v => Show (GMap () v) where ...<br />
</haskell><br />
<br />
Note that class instances are always for particular ''instances'' of a data family and never for an entire family as a whole. This for essentially the same reasons that we cannot define a toplevel function that performs pattern matching on the data constructors of ''different'' instances of a single type family. It would require a form of extensible case construct.<br />
<br />
==== Overlap ====<br />
<br />
The instance declarations of a data family used in a single program may not overlap at all, independent of whether they are associated or not. In contrast to type class instances, this is not only a matter of consistency, but one of type safety.<br />
<br />
=== Import and export ===<br />
<br />
The association of data constructors with type families is more dynamic than that is the case with standard data and newtype declarations. In the standard case, the notation <hask>T(..)</hask> in an import or export list denotes the type constructor and all the data constructors introduced in its declaration. However, a family declaration never introduces any data constructors; instead, data constructors are introduced by family instances. As a result, which data constructors are associated with a type family depends on the currently visible instance declarations for that family. Consequently, an import or export item of the form <hask>T(..)</hask> denotes the family constructor and all currently visible data constructors - in the case of an export item, these may be either imported or defined in the current module. The treatment of import and export items that explicitly list data constructors, such as <hask>GMap(GMapEither)</hask>, is analogous.<br />
<br />
==== Associated families ====<br />
<br />
As expected, an import or export item of the form <hask>C(..)</hask> denotes all of the class' methods and associated types. However, when associated types are explicitly listed as subitems of a class, we need some new syntax, as uppercase identifiers as subitems are usually data constructors, not type constructors. To clarify that we denote types here, each associated type name needs to be prefixed by the keyword <hask>type</hask>. So for example, when explicitly listing the components of the <hask>GMapKey</hask> class, we write <hask>GMapKey(type GMap, empty, lookup, insert)</hask>.<br />
<br />
==== Examples ====<br />
<br />
Assuming our running <hask>GMapKey</hask> class example, let us look at some export lists and their meaning:<br />
<br />
* <hask>module GMap (GMapKey) where...</hask>: Exports just the class name.<br />
* <hask>module GMap (GMapKey(..)) where...</hask>: Exports the class, the associated type <hask>GMap</hask> and the member functions <hask>empty</hask>, <hask>lookup</hask>, and <hask>insert</hask>. None of the data constructors is exported.<br />
* <hask>module GMap (GMapKey(..), GMap(..)) where...</hask>: As before, but also exports all the data constructors <hask>GMapInt</hask>, <hask>GMapChar</hask>, <hask>GMapUnit</hask>, <hask>GMapPair</hask>, and <hask>GMapUnit</hask>.<br />
* <hask>module GMap (GMapKey(empty, lookup, insert), GMap(..)) where...</hask>: As before.<br />
* <hask>module GMap (GMapKey, empty, lookup, insert, GMap(..)) where...</hask>: As before.<br />
<br />
Finally, you can write <hask>GMapKey(type GMap)</hask> to denote both the class <hask>GMapKey</hask> as well as its associated type <hask>GMap</hask>. However, you cannot write <hask>GMapKey(type GMap(..))</hask> &mdash; i.e., sub-component specifications cannot be nested. To specify <hask>GMap</hask>'s data constructors, you have to list it separately.<br />
<br />
==== Instances ====<br />
<br />
Family instances are implicitly exported, just like class instances. However, this applies only to the heads of instances, not to the data constructors an instance defines.<br />
<br />
<br />
== A associated type synonym example ==<br />
<br />
Associated data types are a better alternative for the rather complicated<br />
functional dependencies.<br />
<br />
=== The <hask>class</hask> declaration ===<br />
<br />
Here's an example from the original Functional Dependencies paper:<br />
<haskell><br />
class Collects e ce | ce -> e where<br />
empty :: ce<br />
insert :: e -> ce -> ce<br />
member :: e -> ce -> Bool<br />
toList :: ce -> [e]<br />
</haskell><br />
<br />
With associated type synonyms we can write this as:<br />
<haskell><br />
class Collects ce where<br />
type Elem ce<br />
empty :: ce<br />
insert :: Elem ce -> ce -> ce<br />
member :: Elem ce -> ce -> Bool<br />
toList :: ce -> [Elem ce]<br />
</haskell><br />
That's right, we have dropped from a multi-paramter type class<br />
to a single parameter type class. The parameter <hask>e</hask><br />
has become an associated type <hask>Elem ce</hask>.<br />
<br />
=== An <hask>instance</hask>===<br />
<br />
Here's an instance, with functional dependencies:<br />
<haskell><br />
instance Eq e => Collects e [e] where<br />
empty = []<br />
insert e l = (e:l)<br />
member e [] = False<br />
member e (x:xs) | e == x = True<br />
| otherwise = member e xs<br />
toList l = l<br />
</haskell><br />
<br />
With associated type synonyms, this becomes:<br />
<haskell><br />
instance Eq e => Collects [e] where<br />
type Elem [e] = e<br />
empty = []<br />
insert e l = (e:l)<br />
member e [] = False<br />
member e (x:xs) | e == x = True<br />
| otherwise = member e xs<br />
toList l = l<br />
</haskell><br />
<br />
=== Using generic collections ===<br />
<br />
With Functional Dependencies the code would be:<br />
<haskell><br />
sumCollects :: (Collects e c1,Collects e c2) => c1 -> c2 -> c2<br />
sumCollects c1 c2 = foldr insert c2 (toList c1)<br />
</haskell><br />
<br />
In contrast, with associated type synonyms, we get:<br />
<haskell><br />
sumCollects :: (Collects c1,Collects c2,Elem c1 ~ Elem c2) => c1 -> c2 -> c2<br />
sumCollects c1 c2 = foldr insert c2 (toList c1)<br />
</haskell><br />
<br />
<br />
== Open issues ==<br />
<br />
<br />
None.</div>Tschrijvershttps://wiki.haskell.org/index.php?title=GHC/Type_families&diff=13215GHC/Type families2007-05-25T08:22:07Z<p>Tschrijvers: </p>
<hr />
<div>[[Category:GHC|Indexed types]]<br />
== Data and type families in GHC ==<br />
<br />
Data and type families are a new addition to GHC's type extensions. They are currently an '''experimental''' feature and so their design may still change to some degree. The current implementation covers ''data families'' (including newtypes), which can either be on the toplevel or inside class declarations - the latter are also known as [http://www.cse.unsw.edu.au/~chak/papers/CKPM05.html associated data types]. <br />
<br />
'''NB:''' Please note that type families (and hence also associated type synonyms) are '''not''' fully implemented yet. Any attempt to use them will lead to strange error messages. For the moment, you can only use <hask>data</hask> families.<br />
<br />
== What do I need to use data families? ==<br />
<br />
Indexed type families are implemented in GHC's HEAD (from version 6.7), which you can obtain in binary form from the [http://www.haskell.org/ghc/dist/current/dist/ nightly snapshots] or in source form from the [http://hackage.haskell.org/trac/ghc/wiki/Building/GettingTheSources source repository]. To enable indexed type families in GHC 6.7, you need to supply the compiler option <tt>-ftype-families</tt> (or <tt>-fglasgow-exts</tt>, which implies it). NB: The option used to be called <tt>-findexed-types</tt> for a while.<br />
<br />
== An associated data type example ==<br />
<br />
As an example, consider Ralf Hinze's [http://www.informatik.uni-bonn.de/~ralf/publications.html#J4 generalised tries], a form of generic finite maps. <br />
<br />
=== The class declaration ===<br />
<br />
We define a type class whose instances are the types that we can use as keys in our generic maps:<br />
<haskell><br />
class GMapKey k where<br />
data GMap k :: * -> *<br />
empty :: GMap k v<br />
lookup :: k -> GMap k v -> Maybe v<br />
insert :: k -> v -> GMap k v -> GMap k v<br />
</haskell><br />
The interesting part is the ''associated data family'' declaration of the class. It gives a [http://www.haskell.org/ghc/docs/latest/html/users_guide/type-extensions.html#sec-kinding ''kind signature''] (here <hask>* -> *</hask>) for the associated data type <hask>GMap k</hask> - analog to how methods receive a type signature in a class declaration.<br />
<br />
What it is important to notice is that the first parameter of the associated type <hask>GMap</hask> coincides with the class parameter of <hask>GMapKey</hask>. This indicates that also in all instances of the class, the instances of the associated data type need to have their first argument match up with the instance type. In general, the type arguments of an associated type can be a subset of the class parameters (in a multi-parameter type class) and they can appear in any order, possibly in an order other than in the class head. The latter can be useful if the associated data type is partially applied in some contexts.<br />
<br />
The second important point is that as <hask>GMap k</hask> has kind <hask>* -> *</hask> and <hask>k</hask> (implicitly) has kind <hask>*</hask>, the type constructor <hask>GMap</hask> (without an argument) has kind <hask>* -> * -> *</hask>. Consequently, we see that <hask>GMap</hask> is applied to two arguments in the signatures of the methods <hask>empty</hask>, <hask>lookup</hask>, and <hask>insert</hask>.<br />
<br />
=== An Int instance ===<br />
<br />
To use Ints as keys into generic maps, we declare an instance that simply uses <hask>Data.Map</hask>, thusly:<br />
<haskell><br />
instance GMapKey Int where<br />
data GMap Int v = GMapInt (Data.Map.Map Int v)<br />
empty = GMapInt Data.Map.empty<br />
lookup k (GMapInt m) = Data.Map.lookup k m<br />
insert k v (GMapInt m) = GMapInt (Data.Map.insert k v m)<br />
</haskell><br />
The <hask>Int</hask> instance of the associated data type <hask>GMap</hask> needs to have both of its parameters, but as only the first one corresponds to a class parameter, the second needs to be a type variable (here <hask>v</hask>). As mentioned before any associated type parameter that corresponds to a class parameter must be identical to the class parameter in each instance. The right hand side of the associated data declaration is like that of any other data type.<br />
<br />
NB: At the moment, GADT syntax is not allowed for associated data types (or other indexed types). This is not a fundemental limitation, but just a shortcoming of the current implementation, which we expect to lift in the future.<br />
<br />
As an exercise, implement an instance for <hask>Char</hask> that maps back to the <hask>Int</hask> instance using the conversion functions <hask>Char.ord</hask> and <hask>Char.chr</hask>.<br />
<br />
=== A unit instance ===<br />
<br />
Generic definitions, apart from elementary types, typically cover units, products, and sums. We start here with the unit instance for <hask>GMap</hask>:<br />
<haskell><br />
instance GMapKey () where<br />
data GMap () v = GMapUnit (Maybe v)<br />
empty = GMapUnit Nothing<br />
lookup () (GMapUnit v) = v<br />
insert () v (GMapUnit _) = GMapUnit $ Just v<br />
</haskell><br />
For unit, the map is just a <hask>Maybe</hask> value.<br />
<br />
=== Product and sum instances ===<br />
<br />
Nest, let us define the instances for pairs and sums (i.e., <hask>Either</hask>):<br />
<haskell><br />
instance (GMapKey a, GMapKey b) => GMapKey (a, b) where<br />
data GMap (a, b) v = GMapPair (GMap a (GMap b v))<br />
empty = GMapPair empty<br />
lookup (a, b) (GMapPair gm) = lookup a gm >>= lookup b <br />
insert (a, b) v (GMapPair gm) = GMapPair $ case lookup a gm of<br />
Nothing -> insert a (insert b v empty) gm<br />
Just gm2 -> insert a (insert b v gm2 ) gm<br />
<br />
instance (GMapKey a, GMapKey b) => GMapKey (Either a b) where<br />
data GMap (Either a b) v = GMapEither (GMap a v) (GMap b v)<br />
empty = GMapEither empty empty<br />
lookup (Left a) (GMapEither gm1 _gm2) = lookup a gm1<br />
lookup (Right b) (GMapEither _gm1 gm2 ) = lookup b gm2<br />
insert (Left a) v (GMapEither gm1 gm2) = GMapEither (insert a v gm1) gm2<br />
insert (Right a) v (GMapEither gm1 gm2) = GMapEither gm1 (insert a v gm2)<br />
</haskell><br />
If you find this code algorithmically surprising, I'd suggest to have a look at [http://www.informatik.uni-bonn.de/~ralf/publications.html#J4 Ralf Hinze's paper]. The only novelty concerning associated types, in these two instances, is that the instances have a context <hask>(GMapKey a, GMapKey b)</hask>. Consequently, the right hand sides of the associated type declarations can use <hask>GMap</hask> recursively at the key types <hask>a</hask> and <hask>b</hask> - not unlike the method definitions use the class methods recursively at the types for which the class is given in the instance context.<br />
<br />
=== Using a generic map ===<br />
<br />
Finally, some code building and quering a generic map:<br />
<haskell><br />
myGMap :: GMap (Int, Either Char ()) String<br />
myGMap = insert (5, Left 'c') "(5, Left 'c')" $<br />
insert (4, Right ()) "(4, Right ())" $<br />
insert (5, Right ()) "This is the one!" $<br />
insert (5, Right ()) "This is the two!" $<br />
insert (6, Right ()) "(6, Right ())" $<br />
insert (5, Left 'a') "(5, Left 'a')" $<br />
empty<br />
main = putStrLn $ maybe "Couldn't find key!" id $ lookup (5, Right ()) myGMap<br />
</haskell><br />
<br />
=== Download the code ===<br />
<br />
If you want to play with this example without copying it off the wiki, just download the [http://darcs.haskell.org/testsuite/tests/ghc-regress/indexed-types/should_run/GMapAssoc.hs source code for <hask>GMap</hask>] from GHC's test suite.<br />
<br />
== Definition of the type system extension ==<br />
<br />
['''NB:''' The following material will eventually become documentation for type families in the GHC User Manual. Please help to improve it by forwarding suggestions to <tt>chak@cse.unsw.edu.au</tt>.]<br />
<br />
Data families appear in two flavours: (1) they can be defined on the toplevel or (2) they can appear inside type classes (in which case they are known as associated types). The former is the more general variant, as it lacks the requirement for the type-indexes to coincide with the class parameters. However, the later can lead to more clearly structured code and compiler warnings if some type instances were - possibly accidentally - omitted. In the following, we always discuss the general toplevel form first and then cover the additional constraints placed on associated types.<br />
<br />
=== Family declarations ===<br />
<br />
Indexed data families are introduced by a signature, such as <br />
<haskell><br />
data family GMap k :: * -> *<br />
</haskell><br />
The special <hask>family</hask> distinguishes family from standard data declarations. The result kind annotation is optional and, as usual, defaults to <hask>*</hask> if omitted. An example is<br />
<haskell><br />
data family Array e<br />
</haskell><br />
Named arguments can also be given explicit kind signatures if needed. Just as with [http://www.haskell.org/ghc/docs/latest/html/users_guide/gadt.html GADT declarations] named arguments are entirely optional, so that we can declare <hask>Array</hask> alternatively with<br />
<haskell><br />
data family Array :: * -> *<br />
</haskell><br />
<br />
==== Associated family declarations ====<br />
<br />
When a data family is declared as part of a type class, we drop the <hask>family</hask> special. The <hask>GMap</hask> declaration takes the following form<br />
<haskell><br />
class GMapKey k where<br />
data GMap k :: * -> *<br />
...<br />
</haskell><br />
In contrast to toplevel declarations, named arguments must be used for all type parameters that are to be used as type-indexes. Moreover, the argument names must be class parameters. Each class parameter may only be used at most once per associated type, but some may be omitted and they may be in an order other than in the class head. Hence, the following contrieved example is admissible:<br />
<haskell><br />
class C a b c where<br />
data T c a :: *<br />
</haskell><br />
If kind signatures are required for argument variables, they need to be given in the class head.<br />
<br />
=== Instance declarations ===<br />
<br />
Instance declarations of data and newtype families are very similar to standard data and newtype declarations. The only two differences are that the keyword <hask>data</hask> or <hask>newtype</hask> is followed by <hask>instance</hask> and that some or all of the type arguments can be non-variable types. For example, the <hask>Either</hask> instance for <hask>GMap</hask> is<br />
<haskell><br />
data instance GMap (Either a b) v = GMapEither (GMap a v) (GMap b v)<br />
</haskell><br />
In this example, the declaration has only one variant. In general, it can be be any number.<br />
<br />
Data and newtype instance declarations are only legit when an appropriate family declaration is in scope - just like class instances require the class declaration to be visible. Moreover, each instance declaration has to conform to the kind determined by its family declaration. This implies that the number of parameters of an instance declaration matches the arity determined by the kind of the family. Although, all data families are declared with the <hask>data</hask> keyword, instances can be either <hask>data</hask> or <hask>newtype</hask>s, or a mix of both.<br />
<br />
Even if type families are defined as toplevel declarations, functions that perform different computations for different family instances still need to be defined as methods of type classes. In particular, the following is not possible:<br />
<haskell><br />
data family T a<br />
data instance T Int = A<br />
data instance T Char = B<br />
nonsence :: T a -> Int<br />
nonsence A = 1 -- WRONG: These two equations together...<br />
nonsence B = 2 -- ...will produce a type error.<br />
</haskell><br />
Given the functionality provided by GADTs (Generalised Algebraic Data Types), it might seem as if a definition, such as the above, should be feasible. However, type families are - in contrast to GADTs - are ''open''; i.e., new instances can always be added, possibly in other modules. Supporting pattern matching across different data instances would require a form of extensible case construct.<br />
<br />
==== Associated type instances ====<br />
<br />
When an associated family instance is declared within a type class instance, we drop the <hask>instance</hask> keyword in the family instance. So, the <hask>Either</hask> instance for <hask>GMap</hask> becomes:<br />
<haskell><br />
instance (GMapKey a, GMapKey b) => GMapKey (Either a b) where<br />
data GMap (Either a b) v = GMapEither (GMap a v) (GMap b v<br />
...<br />
</haskell><br />
The most important point about associated family instances is that the type indexes corresponding to class parameters must be identical to the type given in the instance head; here this is first argument of <hask>GMap</hask>, namely <hask>Either a b</hask>, which coincides with the only class parameter. Any parameters to the family constructor that do not correspond to class parameters, need to be variables in every instance; here this is the variable <hask>v</hask>.<br />
<br />
Instances for an associated family can only appear as part of instances declarations of the class in which the family was declared - just as with the equations of the methods of a class. Also in correspondence to how methods are handled, declarations of associated types can be omitted in class instances. If an associated family instance is omitted, the corresponding instance type is not inhabited; i.e., only diverging expressions, such as <hask>undefined</hask>, can assume the type.<br />
<br />
==== Class instances of type instances ====<br />
<br />
Type class instances of instances of data families can be defined as usual, and in particular data instance declarations can have <hask>deriving</hask> clauses. For example, we can write<br />
<haskell><br />
data GMap () v = GMapUnit (Maybe v)<br />
deriving Show<br />
</haskell><br />
which implcitly defines an instance of the form<br />
<haskell><br />
instance Show v => Show (GMap () v) where ...<br />
</haskell><br />
<br />
Note that class instances are always for particular ''instances'' of a data family and never for an entire family as a whole. This for essentially the same reasons that we cannot define a toplevel function that performs pattern matching on the data constructors of ''different'' instances of a single type family. It would require a form of extensible case construct.<br />
<br />
==== Overlap ====<br />
<br />
The instance declarations of a data family used in a single program may not overlap at all, independent of whether they are associated or not. In contrast to type class instances, this is not only a matter of consistency, but one of type safety.<br />
<br />
=== Import and export ===<br />
<br />
The association of data constructors with type families is more dynamic than that is the case with standard data and newtype declarations. In the standard case, the notation <hask>T(..)</hask> in an import or export list denotes the type constructor and all the data constructors introduced in its declaration. However, a family declaration never introduces any data constructors; instead, data constructors are introduced by family instances. As a result, which data constructors are associated with a type family depends on the currently visible instance declarations for that family. Consequently, an import or export item of the form <hask>T(..)</hask> denotes the family constructor and all currently visible data constructors - in the case of an export item, these may be either imported or defined in the current module. The treatment of import and export items that explicitly list data constructors, such as <hask>GMap(GMapEither)</hask>, is analogous.<br />
<br />
==== Associated families ====<br />
<br />
As expected, an import or export item of the form <hask>C(..)</hask> denotes all of the class' methods and associated types. However, when associated types are explicitly listed as subitems of a class, we need some new syntax, as uppercase identifiers as subitems are usually data constructors, not type constructors. To clarify that we denote types here, each associated type name needs to be prefixed by the keyword <hask>type</hask>. So for example, when explicitly listing the components of the <hask>GMapKey</hask> class, we write <hask>GMapKey(type GMap, empty, lookup, insert)</hask>.<br />
<br />
==== Examples ====<br />
<br />
Assuming our running <hask>GMapKey</hask> class example, let us look at some export lists and their meaning:<br />
<br />
* <hask>module GMap (GMapKey) where...</hask>: Exports just the class name.<br />
* <hask>module GMap (GMapKey(..)) where...</hask>: Exports the class, the associated type <hask>GMap</hask> and the member functions <hask>empty</hask>, <hask>lookup</hask>, and <hask>insert</hask>. None of the data constructors is exported.<br />
* <hask>module GMap (GMapKey(..), GMap(..)) where...</hask>: As before, but also exports all the data constructors <hask>GMapInt</hask>, <hask>GMapChar</hask>, <hask>GMapUnit</hask>, <hask>GMapPair</hask>, and <hask>GMapUnit</hask>.<br />
* <hask>module GMap (GMapKey(empty, lookup, insert), GMap(..)) where...</hask>: As before.<br />
* <hask>module GMap (GMapKey, empty, lookup, insert, GMap(..)) where...</hask>: As before.<br />
<br />
Finally, you can write <hask>GMapKey(type GMap)</hask> to denote both the class <hask>GMapKey</hask> as well as its associated type <hask>GMap</hask>. However, you cannot write <hask>GMapKey(type GMap(..))</hask> &mdash; i.e., sub-component specifications cannot be nested. To specify <hask>GMap</hask>'s data constructors, you have to list it separately.<br />
<br />
==== Instances ====<br />
<br />
Family instances are implicitly exported, just like class instances. However, this applies only to the heads of instances, not to the data constructors an instance defines.<br />
<br />
<br />
== A associated type synonym example ==<br />
<br />
Associated data types are a better alternative for the rather complicated<br />
functional dependencies.<br />
<br />
=== The <hask>class</hask> declaration ===<br />
<br />
Here's an example from the original Functional Dependencies paper:<br />
<haskell><br />
class Collects e ce | ce -> e where<br />
empty :: ce<br />
insert :: e -> ce -> ce<br />
member :: e -> ce -> Bool<br />
toList :: ce -> [e]<br />
</haskell><br />
<br />
With associated type synonyms we can write this as:<br />
<haskell><br />
class Collects ce where<br />
type Elem ce<br />
empty :: ce<br />
insert :: Elem ce -> ce -> ce<br />
member :: Elem ce -> ce -> Bool<br />
toList :: ce -> [Elem ce]<br />
</haskell><br />
That's right, we have dropped from a multi-paramter type class<br />
to a single parameter type class. The parameter <hask>e</hask><br />
has become an associated type <hask>Elem ce</hask>.<br />
<br />
=== An <hask>instance</hask>===<br />
<br />
Here's an instance, with functional dependencies:<br />
<haskell><br />
instance Eq e => Collects e [e] where<br />
empty = []<br />
insert e l = (e:l)<br />
member e [] = False<br />
member e (x:xs) | e == x = True<br />
| otherwise = member e xs<br />
toList l = l<br />
</haskell><br />
<br />
With associated type synonyms, this becomes:<br />
<haskell><br />
instance Eq e => Collects [e] where<br />
type Elem [e] = e<br />
empty = []<br />
insert e l = (e:l)<br />
member e [] = False<br />
member e (x:xs) | e == x = True<br />
| otherwise = member e xs<br />
toList l = l<br />
</haskell><br />
<br />
=== Using generic collections ===<br />
<br />
With Functional Dependencies the code would be:<br />
<haskell><br />
sumCollect :: (Collects e c1,Collects e c2) => c1 -> c2 -> c2<br />
sumCollects c1 c2 = foldr insert c2 (toList c1)<br />
</haskell><br />
<br />
In contrast, with associated type synonyms, we get:<br />
<haskell><br />
sumCollect :: (Collects c1,Collects c2,Elem c1 ~ Elem c2) => c1 -> c2 -> c2<br />
sumCollects c1 c2 = foldr insert c2 (toList c1)<br />
</haskell><br />
<br />
<br />
== Open issues ==<br />
<br />
<br />
None.</div>Tschrijvershttps://wiki.haskell.org/index.php?title=GHC/Type_families&diff=13210GHC/Type families2007-05-24T17:02:50Z<p>Tschrijvers: </p>
<hr />
<div>[[Category:GHC|Indexed types]]<br />
== Data and type families in GHC ==<br />
<br />
Data and type families are a new addition to GHC's type extensions. They are currently an '''experimental''' feature and so their design may still change to some degree. The current implementation covers ''data families'' (including newtypes), which can either be on the toplevel or inside class declarations - the latter are also known as [http://www.cse.unsw.edu.au/~chak/papers/CKPM05.html associated data types]. <br />
<br />
'''NB:''' Please note that type families (and hence also associated type synonyms) are '''not''' fully implemented yet. Any attempt to use them will lead to strange error messages. For the moment, you can only use <hask>data</hask> families.<br />
<br />
== What do I need to use data families? ==<br />
<br />
Indexed type families are implemented in GHC's HEAD (from version 6.7), which you can obtain in binary form from the [http://www.haskell.org/ghc/dist/current/dist/ nightly snapshots] or in source form from the [http://hackage.haskell.org/trac/ghc/wiki/Building/GettingTheSources source repository]. To enable indexed type families in GHC 6.7, you need to supply the compiler option <tt>-ftype-families</tt> (or <tt>-fglasgow-exts</tt>, which implies it). NB: The option used to be called <tt>-findexed-types</tt> for a while.<br />
<br />
== An associated data type example ==<br />
<br />
As an example, consider Ralf Hinze's [http://www.informatik.uni-bonn.de/~ralf/publications.html#J4 generalised tries], a form of generic finite maps. <br />
<br />
=== The class declaration ===<br />
<br />
We define a type class whose instances are the types that we can use as keys in our generic maps:<br />
<haskell><br />
class GMapKey k where<br />
data GMap k :: * -> *<br />
empty :: GMap k v<br />
lookup :: k -> GMap k v -> Maybe v<br />
insert :: k -> v -> GMap k v -> GMap k v<br />
</haskell><br />
The interesting part is the ''associated data family'' declaration of the class. It gives a [http://www.haskell.org/ghc/docs/latest/html/users_guide/type-extensions.html#sec-kinding ''kind signature''] (here <hask>* -> *</hask>) for the associated data type <hask>GMap k</hask> - analog to how methods receive a type signature in a class declaration.<br />
<br />
What it is important to notice is that the first parameter of the associated type <hask>GMap</hask> coincides with the class parameter of <hask>GMapKey</hask>. This indicates that also in all instances of the class, the instances of the associated data type need to have their first argument match up with the instance type. In general, the type arguments of an associated type can be a subset of the class parameters (in a multi-parameter type class) and they can appear in any order, possibly in an order other than in the class head. The latter can be useful if the associated data type is partially applied in some contexts.<br />
<br />
The second important point is that as <hask>GMap k</hask> has kind <hask>* -> *</hask> and <hask>k</hask> (implicitly) has kind <hask>*</hask>, the type constructor <hask>GMap</hask> (without an argument) has kind <hask>* -> * -> *</hask>. Consequently, we see that <hask>GMap</hask> is applied to two arguments in the signatures of the methods <hask>empty</hask>, <hask>lookup</hask>, and <hask>insert</hask>.<br />
<br />
=== An Int instance ===<br />
<br />
To use Ints as keys into generic maps, we declare an instance that simply uses <hask>Data.Map</hask>, thusly:<br />
<haskell><br />
instance GMapKey Int where<br />
data GMap Int v = GMapInt (Data.Map.Map Int v)<br />
empty = GMapInt Data.Map.empty<br />
lookup k (GMapInt m) = Data.Map.lookup k m<br />
insert k v (GMapInt m) = GMapInt (Data.Map.insert k v m)<br />
</haskell><br />
The <hask>Int</hask> instance of the associated data type <hask>GMap</hask> needs to have both of its parameters, but as only the first one corresponds to a class parameter, the second needs to be a type variable (here <hask>v</hask>). As mentioned before any associated type parameter that corresponds to a class parameter must be identical to the class parameter in each instance. The right hand side of the associated data declaration is like that of any other data type.<br />
<br />
NB: At the moment, GADT syntax is not allowed for associated data types (or other indexed types). This is not a fundemental limitation, but just a shortcoming of the current implementation, which we expect to lift in the future.<br />
<br />
As an exercise, implement an instance for <hask>Char</hask> that maps back to the <hask>Int</hask> instance using the conversion functions <hask>Char.ord</hask> and <hask>Char.chr</hask>.<br />
<br />
=== A unit instance ===<br />
<br />
Generic definitions, apart from elementary types, typically cover units, products, and sums. We start here with the unit instance for <hask>GMap</hask>:<br />
<haskell><br />
instance GMapKey () where<br />
data GMap () v = GMapUnit (Maybe v)<br />
empty = GMapUnit Nothing<br />
lookup () (GMapUnit v) = v<br />
insert () v (GMapUnit _) = GMapUnit $ Just v<br />
</haskell><br />
For unit, the map is just a <hask>Maybe</hask> value.<br />
<br />
=== Product and sum instances ===<br />
<br />
Nest, let us define the instances for pairs and sums (i.e., <hask>Either</hask>):<br />
<haskell><br />
instance (GMapKey a, GMapKey b) => GMapKey (a, b) where<br />
data GMap (a, b) v = GMapPair (GMap a (GMap b v))<br />
empty = GMapPair empty<br />
lookup (a, b) (GMapPair gm) = lookup a gm >>= lookup b <br />
insert (a, b) v (GMapPair gm) = GMapPair $ case lookup a gm of<br />
Nothing -> insert a (insert b v empty) gm<br />
Just gm2 -> insert a (insert b v gm2 ) gm<br />
<br />
instance (GMapKey a, GMapKey b) => GMapKey (Either a b) where<br />
data GMap (Either a b) v = GMapEither (GMap a v) (GMap b v)<br />
empty = GMapEither empty empty<br />
lookup (Left a) (GMapEither gm1 _gm2) = lookup a gm1<br />
lookup (Right b) (GMapEither _gm1 gm2 ) = lookup b gm2<br />
insert (Left a) v (GMapEither gm1 gm2) = GMapEither (insert a v gm1) gm2<br />
insert (Right a) v (GMapEither gm1 gm2) = GMapEither gm1 (insert a v gm2)<br />
</haskell><br />
If you find this code algorithmically surprising, I'd suggest to have a look at [http://www.informatik.uni-bonn.de/~ralf/publications.html#J4 Ralf Hinze's paper]. The only novelty concerning associated types, in these two instances, is that the instances have a context <hask>(GMapKey a, GMapKey b)</hask>. Consequently, the right hand sides of the associated type declarations can use <hask>GMap</hask> recursively at the key types <hask>a</hask> and <hask>b</hask> - not unlike the method definitions use the class methods recursively at the types for which the class is given in the instance context.<br />
<br />
=== Using a generic map ===<br />
<br />
Finally, some code building and quering a generic map:<br />
<haskell><br />
myGMap :: GMap (Int, Either Char ()) String<br />
myGMap = insert (5, Left 'c') "(5, Left 'c')" $<br />
insert (4, Right ()) "(4, Right ())" $<br />
insert (5, Right ()) "This is the one!" $<br />
insert (5, Right ()) "This is the two!" $<br />
insert (6, Right ()) "(6, Right ())" $<br />
insert (5, Left 'a') "(5, Left 'a')" $<br />
empty<br />
main = putStrLn $ maybe "Couldn't find key!" id $ lookup (5, Right ()) myGMap<br />
</haskell><br />
<br />
=== Download the code ===<br />
<br />
If you want to play with this example without copying it off the wiki, just download the [http://darcs.haskell.org/testsuite/tests/ghc-regress/indexed-types/should_run/GMapAssoc.hs source code for <hask>GMap</hask>] from GHC's test suite.<br />
<br />
== Definition of the type system extension ==<br />
<br />
['''NB:''' The following material will eventually become documentation for type families in the GHC User Manual. Please help to improve it by forwarding suggestions to <tt>chak@cse.unsw.edu.au</tt>.]<br />
<br />
Data families appear in two flavours: (1) they can be defined on the toplevel or (2) they can appear inside type classes (in which case they are known as associated types). The former is the more general variant, as it lacks the requirement for the type-indexes to coincide with the class parameters. However, the later can lead to more clearly structured code and compiler warnings if some type instances were - possibly accidentally - omitted. In the following, we always discuss the general toplevel form first and then cover the additional constraints placed on associated types.<br />
<br />
=== Family declarations ===<br />
<br />
Indexed data families are introduced by a signature, such as <br />
<haskell><br />
data family GMap k :: * -> *<br />
</haskell><br />
The special <hask>family</hask> distinguishes family from standard data declarations. The result kind annotation is optional and, as usual, defaults to <hask>*</hask> if omitted. An example is<br />
<haskell><br />
data family Array e<br />
</haskell><br />
Named arguments can also be given explicit kind signatures if needed. Just as with [http://www.haskell.org/ghc/docs/latest/html/users_guide/gadt.html GADT declarations] named arguments are entirely optional, so that we can declare <hask>Array</hask> alternatively with<br />
<haskell><br />
data family Array :: * -> *<br />
</haskell><br />
<br />
==== Associated family declarations ====<br />
<br />
When a data family is declared as part of a type class, we drop the <hask>family</hask> special. The <hask>GMap</hask> declaration takes the following form<br />
<haskell><br />
class GMapKey k where<br />
data GMap k :: * -> *<br />
...<br />
</haskell><br />
In contrast to toplevel declarations, named arguments must be used for all type parameters that are to be used as type-indexes. Moreover, the argument names must be class parameters. Each class parameter may only be used at most once per associated type, but some may be omitted and they may be in an order other than in the class head. Hence, the following contrieved example is admissible:<br />
<haskell><br />
class C a b c where<br />
data T c a :: *<br />
</haskell><br />
If kind signatures are required for argument variables, they need to be given in the class head.<br />
<br />
=== Instance declarations ===<br />
<br />
Instance declarations of data and newtype families are very similar to standard data and newtype declarations. The only two differences are that the keyword <hask>data</hask> or <hask>newtype</hask> is followed by <hask>instance</hask> and that some or all of the type arguments can be non-variable types. For example, the <hask>Either</hask> instance for <hask>GMap</hask> is<br />
<haskell><br />
data instance GMap (Either a b) v = GMapEither (GMap a v) (GMap b v)<br />
</haskell><br />
In this example, the declaration has only one variant. In general, it can be be any number.<br />
<br />
Data and newtype instance declarations are only legit when an appropriate family declaration is in scope - just like class instances require the class declaration to be visible. Moreover, each instance declaration has to conform to the kind determined by its family declaration. This implies that the number of parameters of an instance declaration matches the arity determined by the kind of the family. Although, all data families are declared with the <hask>data</hask> keyword, instances can be either <hask>data</hask> or <hask>newtype</hask>s, or a mix of both.<br />
<br />
Even if type families are defined as toplevel declarations, functions that perform different computations for different family instances still need to be defined as methods of type classes. In particular, the following is not possible:<br />
<haskell><br />
data family T a<br />
data instance T Int = A<br />
data instance T Char = B<br />
nonsence :: T a -> Int<br />
nonsence A = 1 -- WRONG: These two equations together...<br />
nonsence B = 2 -- ...will produce a type error.<br />
</haskell><br />
Given the functionality provided by GADTs (Generalised Algebraic Data Types), it might seem as if a definition, such as the above, should be feasible. However, type families are - in contrast to GADTs - are ''open''; i.e., new instances can always be added, possibly in other modules. Supporting pattern matching across different data instances would require a form of extensible case construct.<br />
<br />
==== Associated type instances ====<br />
<br />
When an associated family instance is declared within a type class instance, we drop the <hask>instance</hask> keyword in the family instance. So, the <hask>Either</hask> instance for <hask>GMap</hask> becomes:<br />
<haskell><br />
instance (GMapKey a, GMapKey b) => GMapKey (Either a b) where<br />
data GMap (Either a b) v = GMapEither (GMap a v) (GMap b v<br />
...<br />
</haskell><br />
The most important point about associated family instances is that the type indexes corresponding to class parameters must be identical to the type given in the instance head; here this is first argument of <hask>GMap</hask>, namely <hask>Either a b</hask>, which coincides with the only class parameter. Any parameters to the family constructor that do not correspond to class parameters, need to be variables in every instance; here this is the variable <hask>v</hask>.<br />
<br />
Instances for an associated family can only appear as part of instances declarations of the class in which the family was declared - just as with the equations of the methods of a class. Also in correspondence to how methods are handled, declarations of associated types can be omitted in class instances. If an associated family instance is omitted, the corresponding instance type is not inhabited; i.e., only diverging expressions, such as <hask>undefined</hask>, can assume the type.<br />
<br />
==== Class instances of type instances ====<br />
<br />
Type class instances of instances of data families can be defined as usual, and in particular data instance declarations can have <hask>deriving</hask> clauses. For example, we can write<br />
<haskell><br />
data GMap () v = GMapUnit (Maybe v)<br />
deriving Show<br />
</haskell><br />
which implcitly defines an instance of the form<br />
<haskell><br />
instance Show v => Show (GMap () v) where ...<br />
</haskell><br />
<br />
Note that class instances are always for particular ''instances'' of a data family and never for an entire family as a whole. This for essentially the same reasons that we cannot define a toplevel function that performs pattern matching on the data constructors of ''different'' instances of a single type family. It would require a form of extensible case construct.<br />
<br />
==== Overlap ====<br />
<br />
The instance declarations of a data family used in a single program may not overlap at all, independent of whether they are associated or not. In contrast to type class instances, this is not only a matter of consistency, but one of type safety.<br />
<br />
=== Import and export ===<br />
<br />
The association of data constructors with type families is more dynamic than that is the case with standard data and newtype declarations. In the standard case, the notation <hask>T(..)</hask> in an import or export list denotes the type constructor and all the data constructors introduced in its declaration. However, a family declaration never introduces any data constructors; instead, data constructors are introduced by family instances. As a result, which data constructors are associated with a type family depends on the currently visible instance declarations for that family. Consequently, an import or export item of the form <hask>T(..)</hask> denotes the family constructor and all currently visible data constructors - in the case of an export item, these may be either imported or defined in the current module. The treatment of import and export items that explicitly list data constructors, such as <hask>GMap(GMapEither)</hask>, is analogous.<br />
<br />
==== Associated families ====<br />
<br />
As expected, an import or export item of the form <hask>C(..)</hask> denotes all of the class' methods and associated types. However, when associated types are explicitly listed as subitems of a class, we need some new syntax, as uppercase identifiers as subitems are usually data constructors, not type constructors. To clarify that we denote types here, each associated type name needs to be prefixed by the keyword <hask>type</hask>. So for example, when explicitly listing the components of the <hask>GMapKey</hask> class, we write <hask>GMapKey(type GMap, empty, lookup, insert)</hask>.<br />
<br />
==== Examples ====<br />
<br />
Assuming our running <hask>GMapKey</hask> class example, let us look at some export lists and their meaning:<br />
<br />
* <hask>module GMap (GMapKey) where...</hask>: Exports just the class name.<br />
* <hask>module GMap (GMapKey(..)) where...</hask>: Exports the class, the associated type <hask>GMap</hask> and the member functions <hask>empty</hask>, <hask>lookup</hask>, and <hask>insert</hask>. None of the data constructors is exported.<br />
* <hask>module GMap (GMapKey(..), GMap(..)) where...</hask>: As before, but also exports all the data constructors <hask>GMapInt</hask>, <hask>GMapChar</hask>, <hask>GMapUnit</hask>, <hask>GMapPair</hask>, and <hask>GMapUnit</hask>.<br />
* <hask>module GMap (GMapKey(empty, lookup, insert), GMap(..)) where...</hask>: As before.<br />
* <hask>module GMap (GMapKey, empty, lookup, insert, GMap(..)) where...</hask>: As before.<br />
<br />
Finally, you can write <hask>GMapKey(type GMap)</hask> to denote both the class <hask>GMapKey</hask> as well as its associated type <hask>GMap</hask>. However, you cannot write <hask>GMapKey(type GMap(..))</hask> &mdash; i.e., sub-component specifications cannot be nested. To specify <hask>GMap</hask>'s data constructors, you have to list it separately.<br />
<br />
==== Instances ====<br />
<br />
Family instances are implicitly exported, just like class instances. However, this applies only to the heads of instances, not to the data constructors an instance defines.<br />
<br />
<br />
== A associated type synonym example ==<br />
<br />
Associated data types are a better alternative for the rather complicated<br />
functional dependencies.<br />
<br />
=== The Class Declaration ===<br />
<br />
Here's an example from the original Functional Dependencies paper:<br />
<haskell><br />
class Collects e ce | ce -> e where<br />
empty :: ce<br />
insert :: e -> ce -> ce<br />
member :: e -> ce -> Bool<br />
</haskell><br />
<br />
With associated type synonyms we can write this as:<br />
<haskell><br />
class Collects ce where<br />
type Elem ce<br />
empty :: ce<br />
insert :: Elem ce -> ce -> ce<br />
member :: Elem ce -> ce -> Bool<br />
</haskell><br />
That's right, we have dropped from a multi-paramter type class<br />
to a single parameter type class. The parameter <hask>e</hask><br />
has become an associated type <hask>Elem ce</hask>.<br />
<br />
=== An Instance ===<br />
<br />
Here's an instance, with functional dependencies:<br />
<haskell><br />
instance Eq e => Collects e [e] where<br />
empty = []<br />
insert e l = (e:l)<br />
member e [] = False<br />
member e (x:xs) | e == x = True<br />
| otherwise = member e xs<br />
</haskell><br />
<br />
With associated type synonyms, this becomes:<br />
<haskell><br />
instance Eq e => Collects [e] where<br />
type Elem [e] = e<br />
empty = []<br />
insert e l = (e:l)<br />
member e [] = False<br />
member e (x:xs) | e == x = True<br />
| otherwise = member e xs<br />
</haskell><br />
<br />
<br />
<br />
== Open Issues ==<br />
<br />
<br />
None.</div>Tschrijvershttps://wiki.haskell.org/index.php?title=GHC/Type_families&diff=13209GHC/Type families2007-05-24T17:01:18Z<p>Tschrijvers: </p>
<hr />
<div>[[Category:GHC|Indexed types]]<br />
== Data and type families in GHC ==<br />
<br />
Data and type families are a new addition to GHC's type extensions. They are currently an '''experimental''' feature and so their design may still change to some degree. The current implementation covers ''data families'' (including newtypes), which can either be on the toplevel or inside class declarations - the latter are also known as [http://www.cse.unsw.edu.au/~chak/papers/CKPM05.html associated data types]. <br />
<br />
'''NB:''' Please note that type families (and hence also associated type synonyms) are '''not''' fully implemented yet. Any attempt to use them will lead to strange error messages. For the moment, you can only use <hask>data</hask> families.<br />
<br />
== What do I need to use data families? ==<br />
<br />
Indexed type families are implemented in GHC's HEAD (from version 6.7), which you can obtain in binary form from the [http://www.haskell.org/ghc/dist/current/dist/ nightly snapshots] or in source form from the [http://hackage.haskell.org/trac/ghc/wiki/Building/GettingTheSources source repository]. To enable indexed type families in GHC 6.7, you need to supply the compiler option <tt>-ftype-families</tt> (or <tt>-fglasgow-exts</tt>, which implies it). NB: The option used to be called <tt>-findexed-types</tt> for a while.<br />
<br />
== An associated data type example ==<br />
<br />
As an example, consider Ralf Hinze's [http://www.informatik.uni-bonn.de/~ralf/publications.html#J4 generalised tries], a form of generic finite maps. <br />
<br />
=== The class declaration ===<br />
<br />
We define a type class whose instances are the types that we can use as keys in our generic maps:<br />
<haskell><br />
class GMapKey k where<br />
data GMap k :: * -> *<br />
empty :: GMap k v<br />
lookup :: k -> GMap k v -> Maybe v<br />
insert :: k -> v -> GMap k v -> GMap k v<br />
</haskell><br />
The interesting part is the ''associated data family'' declaration of the class. It gives a [http://www.haskell.org/ghc/docs/latest/html/users_guide/type-extensions.html#sec-kinding ''kind signature''] (here <hask>* -> *</hask>) for the associated data type <hask>GMap k</hask> - analog to how methods receive a type signature in a class declaration.<br />
<br />
What it is important to notice is that the first parameter of the associated type <hask>GMap</hask> coincides with the class parameter of <hask>GMapKey</hask>. This indicates that also in all instances of the class, the instances of the associated data type need to have their first argument match up with the instance type. In general, the type arguments of an associated type can be a subset of the class parameters (in a multi-parameter type class) and they can appear in any order, possibly in an order other than in the class head. The latter can be useful if the associated data type is partially applied in some contexts.<br />
<br />
The second important point is that as <hask>GMap k</hask> has kind <hask>* -> *</hask> and <hask>k</hask> (implicitly) has kind <hask>*</hask>, the type constructor <hask>GMap</hask> (without an argument) has kind <hask>* -> * -> *</hask>. Consequently, we see that <hask>GMap</hask> is applied to two arguments in the signatures of the methods <hask>empty</hask>, <hask>lookup</hask>, and <hask>insert</hask>.<br />
<br />
=== An Int instance ===<br />
<br />
To use Ints as keys into generic maps, we declare an instance that simply uses <hask>Data.Map</hask>, thusly:<br />
<haskell><br />
instance GMapKey Int where<br />
data GMap Int v = GMapInt (Data.Map.Map Int v)<br />
empty = GMapInt Data.Map.empty<br />
lookup k (GMapInt m) = Data.Map.lookup k m<br />
insert k v (GMapInt m) = GMapInt (Data.Map.insert k v m)<br />
</haskell><br />
The <hask>Int</hask> instance of the associated data type <hask>GMap</hask> needs to have both of its parameters, but as only the first one corresponds to a class parameter, the second needs to be a type variable (here <hask>v</hask>). As mentioned before any associated type parameter that corresponds to a class parameter must be identical to the class parameter in each instance. The right hand side of the associated data declaration is like that of any other data type.<br />
<br />
NB: At the moment, GADT syntax is not allowed for associated data types (or other indexed types). This is not a fundemental limitation, but just a shortcoming of the current implementation, which we expect to lift in the future.<br />
<br />
As an exercise, implement an instance for <hask>Char</hask> that maps back to the <hask>Int</hask> instance using the conversion functions <hask>Char.ord</hask> and <hask>Char.chr</hask>.<br />
<br />
=== A unit instance ===<br />
<br />
Generic definitions, apart from elementary types, typically cover units, products, and sums. We start here with the unit instance for <hask>GMap</hask>:<br />
<haskell><br />
instance GMapKey () where<br />
data GMap () v = GMapUnit (Maybe v)<br />
empty = GMapUnit Nothing<br />
lookup () (GMapUnit v) = v<br />
insert () v (GMapUnit _) = GMapUnit $ Just v<br />
</haskell><br />
For unit, the map is just a <hask>Maybe</hask> value.<br />
<br />
=== Product and sum instances ===<br />
<br />
Nest, let us define the instances for pairs and sums (i.e., <hask>Either</hask>):<br />
<haskell><br />
instance (GMapKey a, GMapKey b) => GMapKey (a, b) where<br />
data GMap (a, b) v = GMapPair (GMap a (GMap b v))<br />
empty = GMapPair empty<br />
lookup (a, b) (GMapPair gm) = lookup a gm >>= lookup b <br />
insert (a, b) v (GMapPair gm) = GMapPair $ case lookup a gm of<br />
Nothing -> insert a (insert b v empty) gm<br />
Just gm2 -> insert a (insert b v gm2 ) gm<br />
<br />
instance (GMapKey a, GMapKey b) => GMapKey (Either a b) where<br />
data GMap (Either a b) v = GMapEither (GMap a v) (GMap b v)<br />
empty = GMapEither empty empty<br />
lookup (Left a) (GMapEither gm1 _gm2) = lookup a gm1<br />
lookup (Right b) (GMapEither _gm1 gm2 ) = lookup b gm2<br />
insert (Left a) v (GMapEither gm1 gm2) = GMapEither (insert a v gm1) gm2<br />
insert (Right a) v (GMapEither gm1 gm2) = GMapEither gm1 (insert a v gm2)<br />
</haskell><br />
If you find this code algorithmically surprising, I'd suggest to have a look at [http://www.informatik.uni-bonn.de/~ralf/publications.html#J4 Ralf Hinze's paper]. The only novelty concerning associated types, in these two instances, is that the instances have a context <hask>(GMapKey a, GMapKey b)</hask>. Consequently, the right hand sides of the associated type declarations can use <hask>GMap</hask> recursively at the key types <hask>a</hask> and <hask>b</hask> - not unlike the method definitions use the class methods recursively at the types for which the class is given in the instance context.<br />
<br />
=== Using a generic map ===<br />
<br />
Finally, some code building and quering a generic map:<br />
<haskell><br />
myGMap :: GMap (Int, Either Char ()) String<br />
myGMap = insert (5, Left 'c') "(5, Left 'c')" $<br />
insert (4, Right ()) "(4, Right ())" $<br />
insert (5, Right ()) "This is the one!" $<br />
insert (5, Right ()) "This is the two!" $<br />
insert (6, Right ()) "(6, Right ())" $<br />
insert (5, Left 'a') "(5, Left 'a')" $<br />
empty<br />
main = putStrLn $ maybe "Couldn't find key!" id $ lookup (5, Right ()) myGMap<br />
</haskell><br />
<br />
=== Download the code ===<br />
<br />
If you want to play with this example without copying it off the wiki, just download the [http://darcs.haskell.org/testsuite/tests/ghc-regress/indexed-types/should_run/GMapAssoc.hs source code for <hask>GMap</hask>] from GHC's test suite.<br />
<br />
== Definition of the type system extension ==<br />
<br />
['''NB:''' The following material will eventually become documentation for type families in the GHC User Manual. Please help to improve it by forwarding suggestions to <tt>chak@cse.unsw.edu.au</tt>.]<br />
<br />
Data families appear in two flavours: (1) they can be defined on the toplevel or (2) they can appear inside type classes (in which case they are known as associated types). The former is the more general variant, as it lacks the requirement for the type-indexes to coincide with the class parameters. However, the later can lead to more clearly structured code and compiler warnings if some type instances were - possibly accidentally - omitted. In the following, we always discuss the general toplevel form first and then cover the additional constraints placed on associated types.<br />
<br />
=== Family declarations ===<br />
<br />
Indexed data families are introduced by a signature, such as <br />
<haskell><br />
data family GMap k :: * -> *<br />
</haskell><br />
The special <hask>family</hask> distinguishes family from standard data declarations. The result kind annotation is optional and, as usual, defaults to <hask>*</hask> if omitted. An example is<br />
<haskell><br />
data family Array e<br />
</haskell><br />
Named arguments can also be given explicit kind signatures if needed. Just as with [http://www.haskell.org/ghc/docs/latest/html/users_guide/gadt.html GADT declarations] named arguments are entirely optional, so that we can declare <hask>Array</hask> alternatively with<br />
<haskell><br />
data family Array :: * -> *<br />
</haskell><br />
<br />
==== Associated family declarations ====<br />
<br />
When a data family is declared as part of a type class, we drop the <hask>family</hask> special. The <hask>GMap</hask> declaration takes the following form<br />
<haskell><br />
class GMapKey k where<br />
data GMap k :: * -> *<br />
...<br />
</haskell><br />
In contrast to toplevel declarations, named arguments must be used for all type parameters that are to be used as type-indexes. Moreover, the argument names must be class parameters. Each class parameter may only be used at most once per associated type, but some may be omitted and they may be in an order other than in the class head. Hence, the following contrieved example is admissible:<br />
<haskell><br />
class C a b c where<br />
data T c a :: *<br />
</haskell><br />
If kind signatures are required for argument variables, they need to be given in the class head.<br />
<br />
=== Instance declarations ===<br />
<br />
Instance declarations of data and newtype families are very similar to standard data and newtype declarations. The only two differences are that the keyword <hask>data</hask> or <hask>newtype</hask> is followed by <hask>instance</hask> and that some or all of the type arguments can be non-variable types. For example, the <hask>Either</hask> instance for <hask>GMap</hask> is<br />
<haskell><br />
data instance GMap (Either a b) v = GMapEither (GMap a v) (GMap b v)<br />
</haskell><br />
In this example, the declaration has only one variant. In general, it can be be any number.<br />
<br />
Data and newtype instance declarations are only legit when an appropriate family declaration is in scope - just like class instances require the class declaration to be visible. Moreover, each instance declaration has to conform to the kind determined by its family declaration. This implies that the number of parameters of an instance declaration matches the arity determined by the kind of the family. Although, all data families are declared with the <hask>data</hask> keyword, instances can be either <hask>data</hask> or <hask>newtype</hask>s, or a mix of both.<br />
<br />
Even if type families are defined as toplevel declarations, functions that perform different computations for different family instances still need to be defined as methods of type classes. In particular, the following is not possible:<br />
<haskell><br />
data family T a<br />
data instance T Int = A<br />
data instance T Char = B<br />
nonsence :: T a -> Int<br />
nonsence A = 1 -- WRONG: These two equations together...<br />
nonsence B = 2 -- ...will produce a type error.<br />
</haskell><br />
Given the functionality provided by GADTs (Generalised Algebraic Data Types), it might seem as if a definition, such as the above, should be feasible. However, type families are - in contrast to GADTs - are ''open''; i.e., new instances can always be added, possibly in other modules. Supporting pattern matching across different data instances would require a form of extensible case construct.<br />
<br />
==== Associated type instances ====<br />
<br />
When an associated family instance is declared within a type class instance, we drop the <hask>instance</hask> keyword in the family instance. So, the <hask>Either</hask> instance for <hask>GMap</hask> becomes:<br />
<haskell><br />
instance (GMapKey a, GMapKey b) => GMapKey (Either a b) where<br />
data GMap (Either a b) v = GMapEither (GMap a v) (GMap b v<br />
...<br />
</haskell><br />
The most important point about associated family instances is that the type indexes corresponding to class parameters must be identical to the type given in the instance head; here this is first argument of <hask>GMap</hask>, namely <hask>Either a b</hask>, which coincides with the only class parameter. Any parameters to the family constructor that do not correspond to class parameters, need to be variables in every instance; here this is the variable <hask>v</hask>.<br />
<br />
Instances for an associated family can only appear as part of instances declarations of the class in which the family was declared - just as with the equations of the methods of a class. Also in correspondence to how methods are handled, declarations of associated types can be omitted in class instances. If an associated family instance is omitted, the corresponding instance type is not inhabited; i.e., only diverging expressions, such as <hask>undefined</hask>, can assume the type.<br />
<br />
==== Class instances of type instances ====<br />
<br />
Type class instances of instances of data families can be defined as usual, and in particular data instance declarations can have <hask>deriving</hask> clauses. For example, we can write<br />
<haskell><br />
data GMap () v = GMapUnit (Maybe v)<br />
deriving Show<br />
</haskell><br />
which implcitly defines an instance of the form<br />
<haskell><br />
instance Show v => Show (GMap () v) where ...<br />
</haskell><br />
<br />
Note that class instances are always for particular ''instances'' of a data family and never for an entire family as a whole. This for essentially the same reasons that we cannot define a toplevel function that performs pattern matching on the data constructors of ''different'' instances of a single type family. It would require a form of extensible case construct.<br />
<br />
==== Overlap ====<br />
<br />
The instance declarations of a data family used in a single program may not overlap at all, independent of whether they are associated or not. In contrast to type class instances, this is not only a matter of consistency, but one of type safety.<br />
<br />
=== Import and export ===<br />
<br />
The association of data constructors with type families is more dynamic than that is the case with standard data and newtype declarations. In the standard case, the notation <hask>T(..)</hask> in an import or export list denotes the type constructor and all the data constructors introduced in its declaration. However, a family declaration never introduces any data constructors; instead, data constructors are introduced by family instances. As a result, which data constructors are associated with a type family depends on the currently visible instance declarations for that family. Consequently, an import or export item of the form <hask>T(..)</hask> denotes the family constructor and all currently visible data constructors - in the case of an export item, these may be either imported or defined in the current module. The treatment of import and export items that explicitly list data constructors, such as <hask>GMap(GMapEither)</hask>, is analogous.<br />
<br />
==== Associated families ====<br />
<br />
As expected, an import or export item of the form <hask>C(..)</hask> denotes all of the class' methods and associated types. However, when associated types are explicitly listed as subitems of a class, we need some new syntax, as uppercase identifiers as subitems are usually data constructors, not type constructors. To clarify that we denote types here, each associated type name needs to be prefixed by the keyword <hask>type</hask>. So for example, when explicitly listing the components of the <hask>GMapKey</hask> class, we write <hask>GMapKey(type GMap, empty, lookup, insert)</hask>.<br />
<br />
==== Examples ====<br />
<br />
Assuming our running <hask>GMapKey</hask> class example, let us look at some export lists and their meaning:<br />
<br />
* <hask>module GMap (GMapKey) where...</hask>: Exports just the class name.<br />
* <hask>module GMap (GMapKey(..)) where...</hask>: Exports the class, the associated type <hask>GMap</hask> and the member functions <hask>empty</hask>, <hask>lookup</hask>, and <hask>insert</hask>. None of the data constructors is exported.<br />
* <hask>module GMap (GMapKey(..), GMap(..)) where...</hask>: As before, but also exports all the data constructors <hask>GMapInt</hask>, <hask>GMapChar</hask>, <hask>GMapUnit</hask>, <hask>GMapPair</hask>, and <hask>GMapUnit</hask>.<br />
* <hask>module GMap (GMapKey(empty, lookup, insert), GMap(..)) where...</hask>: As before.<br />
* <hask>module GMap (GMapKey, empty, lookup, insert, GMap(..)) where...</hask>: As before.<br />
<br />
Finally, you can write <hask>GMapKey(type GMap)</hask> to denote both the class <hask>GMapKey</hask> as well as its associated type <hask>GMap</hask>. However, you cannot write <hask>GMapKey(type GMap(..))</hask> &mdash; i.e., sub-component specifications cannot be nested. To specify <hask>GMap</hask>'s data constructors, you have to list it separately.<br />
<br />
==== Instances ====<br />
<br />
Family instances are implicitly exported, just like class instances. However, this applies only to the heads of instances, not to the data constructors an instance defines.<br />
<br />
<br />
== A associated type synonym example ==<br />
<br />
Associated data types are a better alternative for the rather complicated<br />
functional dependencies.<br />
<br />
=== The Class Declaration ===<br />
<br />
Here's an example from the original Functional Dependencies paper:<br />
<haskell><br />
class Collects e ce | ce -> e where<br />
empty :: ce<br />
insert :: e -> ce -> ce<br />
member :: e -> ce -> Bool<br />
</haskell><br />
<br />
With associated type synonyms we can write this as:<br />
<haskell><br />
class Collects ce where<br />
type Elem ce<br />
empty :: ce<br />
insert :: Elem ce -> ce -> ce<br />
member :: Elem ce -> ce -> Bool<br />
</haskell><br />
That's right, we have dropped from a multi-paramter type class<br />
to a single parameter type class. The parameter <hask>e</hask><br />
has become an associated type <hask>Elem ce</hask>.<br />
<br />
=== An Instance ===<br />
<br />
Here's an instance, with functional dependencies:<br />
<haskell><br />
instance Eq e => Collects e [e] where<br />
empty = []<br />
insert e l = (e:l)<br />
member e [] = False<br />
member e (x:xs) | e == x = True<br />
| otherwise = member e xs<br />
</haskell><br />
<br />
<br />
<br />
== Open Issues ==<br />
<br />
None.</div>Tschrijvershttps://wiki.haskell.org/index.php?title=GHC/Type_families&diff=13208GHC/Type families2007-05-24T16:57:29Z<p>Tschrijvers: </p>
<hr />
<div>[[Category:GHC|Indexed types]]<br />
== Data and type families in GHC ==<br />
<br />
Data and type families are a new addition to GHC's type extensions. They are currently an '''experimental''' feature and so their design may still change to some degree. The current implementation covers ''data families'' (including newtypes), which can either be on the toplevel or inside class declarations - the latter are also known as [http://www.cse.unsw.edu.au/~chak/papers/CKPM05.html associated data types]. <br />
<br />
'''NB:''' Please note that type families (and hence also associated type synonyms) are '''not''' fully implemented yet. Any attempt to use them will lead to strange error messages. For the moment, you can only use <hask>data</hask> families.<br />
<br />
== What do I need to use data families? ==<br />
<br />
Indexed type families are implemented in GHC's HEAD (from version 6.7), which you can obtain in binary form from the [http://www.haskell.org/ghc/dist/current/dist/ nightly snapshots] or in source form from the [http://hackage.haskell.org/trac/ghc/wiki/Building/GettingTheSources source repository]. To enable indexed type families in GHC 6.7, you need to supply the compiler option <tt>-ftype-families</tt> (or <tt>-fglasgow-exts</tt>, which implies it). NB: The option used to be called <tt>-findexed-types</tt> for a while.<br />
<br />
== An associated data type example ==<br />
<br />
As an example, consider Ralf Hinze's [http://www.informatik.uni-bonn.de/~ralf/publications.html#J4 generalised tries], a form of generic finite maps. <br />
<br />
=== The class declaration ===<br />
<br />
We define a type class whose instances are the types that we can use as keys in our generic maps:<br />
<haskell><br />
class GMapKey k where<br />
data GMap k :: * -> *<br />
empty :: GMap k v<br />
lookup :: k -> GMap k v -> Maybe v<br />
insert :: k -> v -> GMap k v -> GMap k v<br />
</haskell><br />
The interesting part is the ''associated data family'' declaration of the class. It gives a [http://www.haskell.org/ghc/docs/latest/html/users_guide/type-extensions.html#sec-kinding ''kind signature''] (here <hask>* -> *</hask>) for the associated data type <hask>GMap k</hask> - analog to how methods receive a type signature in a class declaration.<br />
<br />
What it is important to notice is that the first parameter of the associated type <hask>GMap</hask> coincides with the class parameter of <hask>GMapKey</hask>. This indicates that also in all instances of the class, the instances of the associated data type need to have their first argument match up with the instance type. In general, the type arguments of an associated type can be a subset of the class parameters (in a multi-parameter type class) and they can appear in any order, possibly in an order other than in the class head. The latter can be useful if the associated data type is partially applied in some contexts.<br />
<br />
The second important point is that as <hask>GMap k</hask> has kind <hask>* -> *</hask> and <hask>k</hask> (implicitly) has kind <hask>*</hask>, the type constructor <hask>GMap</hask> (without an argument) has kind <hask>* -> * -> *</hask>. Consequently, we see that <hask>GMap</hask> is applied to two arguments in the signatures of the methods <hask>empty</hask>, <hask>lookup</hask>, and <hask>insert</hask>.<br />
<br />
=== An Int instance ===<br />
<br />
To use Ints as keys into generic maps, we declare an instance that simply uses <hask>Data.Map</hask>, thusly:<br />
<haskell><br />
instance GMapKey Int where<br />
data GMap Int v = GMapInt (Data.Map.Map Int v)<br />
empty = GMapInt Data.Map.empty<br />
lookup k (GMapInt m) = Data.Map.lookup k m<br />
insert k v (GMapInt m) = GMapInt (Data.Map.insert k v m)<br />
</haskell><br />
The <hask>Int</hask> instance of the associated data type <hask>GMap</hask> needs to have both of its parameters, but as only the first one corresponds to a class parameter, the second needs to be a type variable (here <hask>v</hask>). As mentioned before any associated type parameter that corresponds to a class parameter must be identical to the class parameter in each instance. The right hand side of the associated data declaration is like that of any other data type.<br />
<br />
NB: At the moment, GADT syntax is not allowed for associated data types (or other indexed types). This is not a fundemental limitation, but just a shortcoming of the current implementation, which we expect to lift in the future.<br />
<br />
As an exercise, implement an instance for <hask>Char</hask> that maps back to the <hask>Int</hask> instance using the conversion functions <hask>Char.ord</hask> and <hask>Char.chr</hask>.<br />
<br />
=== A unit instance ===<br />
<br />
Generic definitions, apart from elementary types, typically cover units, products, and sums. We start here with the unit instance for <hask>GMap</hask>:<br />
<haskell><br />
instance GMapKey () where<br />
data GMap () v = GMapUnit (Maybe v)<br />
empty = GMapUnit Nothing<br />
lookup () (GMapUnit v) = v<br />
insert () v (GMapUnit _) = GMapUnit $ Just v<br />
</haskell><br />
For unit, the map is just a <hask>Maybe</hask> value.<br />
<br />
=== Product and sum instances ===<br />
<br />
Nest, let us define the instances for pairs and sums (i.e., <hask>Either</hask>):<br />
<haskell><br />
instance (GMapKey a, GMapKey b) => GMapKey (a, b) where<br />
data GMap (a, b) v = GMapPair (GMap a (GMap b v))<br />
empty = GMapPair empty<br />
lookup (a, b) (GMapPair gm) = lookup a gm >>= lookup b <br />
insert (a, b) v (GMapPair gm) = GMapPair $ case lookup a gm of<br />
Nothing -> insert a (insert b v empty) gm<br />
Just gm2 -> insert a (insert b v gm2 ) gm<br />
<br />
instance (GMapKey a, GMapKey b) => GMapKey (Either a b) where<br />
data GMap (Either a b) v = GMapEither (GMap a v) (GMap b v)<br />
empty = GMapEither empty empty<br />
lookup (Left a) (GMapEither gm1 _gm2) = lookup a gm1<br />
lookup (Right b) (GMapEither _gm1 gm2 ) = lookup b gm2<br />
insert (Left a) v (GMapEither gm1 gm2) = GMapEither (insert a v gm1) gm2<br />
insert (Right a) v (GMapEither gm1 gm2) = GMapEither gm1 (insert a v gm2)<br />
</haskell><br />
If you find this code algorithmically surprising, I'd suggest to have a look at [http://www.informatik.uni-bonn.de/~ralf/publications.html#J4 Ralf Hinze's paper]. The only novelty concerning associated types, in these two instances, is that the instances have a context <hask>(GMapKey a, GMapKey b)</hask>. Consequently, the right hand sides of the associated type declarations can use <hask>GMap</hask> recursively at the key types <hask>a</hask> and <hask>b</hask> - not unlike the method definitions use the class methods recursively at the types for which the class is given in the instance context.<br />
<br />
=== Using a generic map ===<br />
<br />
Finally, some code building and quering a generic map:<br />
<haskell><br />
myGMap :: GMap (Int, Either Char ()) String<br />
myGMap = insert (5, Left 'c') "(5, Left 'c')" $<br />
insert (4, Right ()) "(4, Right ())" $<br />
insert (5, Right ()) "This is the one!" $<br />
insert (5, Right ()) "This is the two!" $<br />
insert (6, Right ()) "(6, Right ())" $<br />
insert (5, Left 'a') "(5, Left 'a')" $<br />
empty<br />
main = putStrLn $ maybe "Couldn't find key!" id $ lookup (5, Right ()) myGMap<br />
</haskell><br />
<br />
=== Download the code ===<br />
<br />
If you want to play with this example without copying it off the wiki, just download the [http://darcs.haskell.org/testsuite/tests/ghc-regress/indexed-types/should_run/GMapAssoc.hs source code for <hask>GMap</hask>] from GHC's test suite.<br />
<br />
== Definition of the type system extension ==<br />
<br />
['''NB:''' The following material will eventually become documentation for type families in the GHC User Manual. Please help to improve it by forwarding suggestions to <tt>chak@cse.unsw.edu.au</tt>.]<br />
<br />
Data families appear in two flavours: (1) they can be defined on the toplevel or (2) they can appear inside type classes (in which case they are known as associated types). The former is the more general variant, as it lacks the requirement for the type-indexes to coincide with the class parameters. However, the later can lead to more clearly structured code and compiler warnings if some type instances were - possibly accidentally - omitted. In the following, we always discuss the general toplevel form first and then cover the additional constraints placed on associated types.<br />
<br />
=== Family declarations ===<br />
<br />
Indexed data families are introduced by a signature, such as <br />
<haskell><br />
data family GMap k :: * -> *<br />
</haskell><br />
The special <hask>family</hask> distinguishes family from standard data declarations. The result kind annotation is optional and, as usual, defaults to <hask>*</hask> if omitted. An example is<br />
<haskell><br />
data family Array e<br />
</haskell><br />
Named arguments can also be given explicit kind signatures if needed. Just as with [http://www.haskell.org/ghc/docs/latest/html/users_guide/gadt.html GADT declarations] named arguments are entirely optional, so that we can declare <hask>Array</hask> alternatively with<br />
<haskell><br />
data family Array :: * -> *<br />
</haskell><br />
<br />
==== Associated family declarations ====<br />
<br />
When a data family is declared as part of a type class, we drop the <hask>family</hask> special. The <hask>GMap</hask> declaration takes the following form<br />
<haskell><br />
class GMapKey k where<br />
data GMap k :: * -> *<br />
...<br />
</haskell><br />
In contrast to toplevel declarations, named arguments must be used for all type parameters that are to be used as type-indexes. Moreover, the argument names must be class parameters. Each class parameter may only be used at most once per associated type, but some may be omitted and they may be in an order other than in the class head. Hence, the following contrieved example is admissible:<br />
<haskell><br />
class C a b c where<br />
data T c a :: *<br />
</haskell><br />
If kind signatures are required for argument variables, they need to be given in the class head.<br />
<br />
=== Instance declarations ===<br />
<br />
Instance declarations of data and newtype families are very similar to standard data and newtype declarations. The only two differences are that the keyword <hask>data</hask> or <hask>newtype</hask> is followed by <hask>instance</hask> and that some or all of the type arguments can be non-variable types. For example, the <hask>Either</hask> instance for <hask>GMap</hask> is<br />
<haskell><br />
data instance GMap (Either a b) v = GMapEither (GMap a v) (GMap b v)<br />
</haskell><br />
In this example, the declaration has only one variant. In general, it can be be any number.<br />
<br />
Data and newtype instance declarations are only legit when an appropriate family declaration is in scope - just like class instances require the class declaration to be visible. Moreover, each instance declaration has to conform to the kind determined by its family declaration. This implies that the number of parameters of an instance declaration matches the arity determined by the kind of the family. Although, all data families are declared with the <hask>data</hask> keyword, instances can be either <hask>data</hask> or <hask>newtype</hask>s, or a mix of both.<br />
<br />
Even if type families are defined as toplevel declarations, functions that perform different computations for different family instances still need to be defined as methods of type classes. In particular, the following is not possible:<br />
<haskell><br />
data family T a<br />
data instance T Int = A<br />
data instance T Char = B<br />
nonsence :: T a -> Int<br />
nonsence A = 1 -- WRONG: These two equations together...<br />
nonsence B = 2 -- ...will produce a type error.<br />
</haskell><br />
Given the functionality provided by GADTs (Generalised Algebraic Data Types), it might seem as if a definition, such as the above, should be feasible. However, type families are - in contrast to GADTs - are ''open''; i.e., new instances can always be added, possibly in other modules. Supporting pattern matching across different data instances would require a form of extensible case construct.<br />
<br />
==== Associated type instances ====<br />
<br />
When an associated family instance is declared within a type class instance, we drop the <hask>instance</hask> keyword in the family instance. So, the <hask>Either</hask> instance for <hask>GMap</hask> becomes:<br />
<haskell><br />
instance (GMapKey a, GMapKey b) => GMapKey (Either a b) where<br />
data GMap (Either a b) v = GMapEither (GMap a v) (GMap b v<br />
...<br />
</haskell><br />
The most important point about associated family instances is that the type indexes corresponding to class parameters must be identical to the type given in the instance head; here this is first argument of <hask>GMap</hask>, namely <hask>Either a b</hask>, which coincides with the only class parameter. Any parameters to the family constructor that do not correspond to class parameters, need to be variables in every instance; here this is the variable <hask>v</hask>.<br />
<br />
Instances for an associated family can only appear as part of instances declarations of the class in which the family was declared - just as with the equations of the methods of a class. Also in correspondence to how methods are handled, declarations of associated types can be omitted in class instances. If an associated family instance is omitted, the corresponding instance type is not inhabited; i.e., only diverging expressions, such as <hask>undefined</hask>, can assume the type.<br />
<br />
==== Class instances of type instances ====<br />
<br />
Type class instances of instances of data families can be defined as usual, and in particular data instance declarations can have <hask>deriving</hask> clauses. For example, we can write<br />
<haskell><br />
data GMap () v = GMapUnit (Maybe v)<br />
deriving Show<br />
</haskell><br />
which implcitly defines an instance of the form<br />
<haskell><br />
instance Show v => Show (GMap () v) where ...<br />
</haskell><br />
<br />
Note that class instances are always for particular ''instances'' of a data family and never for an entire family as a whole. This for essentially the same reasons that we cannot define a toplevel function that performs pattern matching on the data constructors of ''different'' instances of a single type family. It would require a form of extensible case construct.<br />
<br />
==== Overlap ====<br />
<br />
The instance declarations of a data family used in a single program may not overlap at all, independent of whether they are associated or not. In contrast to type class instances, this is not only a matter of consistency, but one of type safety.<br />
<br />
=== Import and export ===<br />
<br />
The association of data constructors with type families is more dynamic than that is the case with standard data and newtype declarations. In the standard case, the notation <hask>T(..)</hask> in an import or export list denotes the type constructor and all the data constructors introduced in its declaration. However, a family declaration never introduces any data constructors; instead, data constructors are introduced by family instances. As a result, which data constructors are associated with a type family depends on the currently visible instance declarations for that family. Consequently, an import or export item of the form <hask>T(..)</hask> denotes the family constructor and all currently visible data constructors - in the case of an export item, these may be either imported or defined in the current module. The treatment of import and export items that explicitly list data constructors, such as <hask>GMap(GMapEither)</hask>, is analogous.<br />
<br />
==== Associated families ====<br />
<br />
As expected, an import or export item of the form <hask>C(..)</hask> denotes all of the class' methods and associated types. However, when associated types are explicitly listed as subitems of a class, we need some new syntax, as uppercase identifiers as subitems are usually data constructors, not type constructors. To clarify that we denote types here, each associated type name needs to be prefixed by the keyword <hask>type</hask>. So for example, when explicitly listing the components of the <hask>GMapKey</hask> class, we write <hask>GMapKey(type GMap, empty, lookup, insert)</hask>.<br />
<br />
==== Examples ====<br />
<br />
Assuming our running <hask>GMapKey</hask> class example, let us look at some export lists and their meaning:<br />
<br />
* <hask>module GMap (GMapKey) where...</hask>: Exports just the class name.<br />
* <hask>module GMap (GMapKey(..)) where...</hask>: Exports the class, the associated type <hask>GMap</hask> and the member functions <hask>empty</hask>, <hask>lookup</hask>, and <hask>insert</hask>. None of the data constructors is exported.<br />
* <hask>module GMap (GMapKey(..), GMap(..)) where...</hask>: As before, but also exports all the data constructors <hask>GMapInt</hask>, <hask>GMapChar</hask>, <hask>GMapUnit</hask>, <hask>GMapPair</hask>, and <hask>GMapUnit</hask>.<br />
* <hask>module GMap (GMapKey(empty, lookup, insert), GMap(..)) where...</hask>: As before.<br />
* <hask>module GMap (GMapKey, empty, lookup, insert, GMap(..)) where...</hask>: As before.<br />
<br />
Finally, you can write <hask>GMapKey(type GMap)</hask> to denote both the class <hask>GMapKey</hask> as well as its associated type <hask>GMap</hask>. However, you cannot write <hask>GMapKey(type GMap(..))</hask> &mdash; i.e., sub-component specifications cannot be nested. To specify <hask>GMap</hask>'s data constructors, you have to list it separately.<br />
<br />
==== Instances ====<br />
<br />
Family instances are implicitly exported, just like class instances. However, this applies only to the heads of instances, not to the data constructors an instance defines.<br />
<br />
<br />
== A associated type synonym example ==<br />
<br />
Associated data types are a better alternative for the rather complicated<br />
functional dependencies.<br />
<br />
=== The Class Declaration ===<br />
<br />
Here's an example from the original Functional Dependencies paper:<br />
<haskell><br />
class Collects e ce | ce -> e where<br />
empty :: ce<br />
insert :: e -> ce -> ce<br />
member :: e -> ce -> Bool<br />
</haskell><br />
<br />
With associated type synonyms we can write this as:<br />
<haskell><br />
class Collects ce where<br />
type Elem ce<br />
empty :: ce<br />
insert :: Elem ce -> ce -> ce<br />
member :: Elem ce -> ce -> Bool<br />
</haskell><br />
That's right, we have dropped from a multi-paramter type class<br />
to a single parameter type class. The parameter <hask>e</hask><br />
has become an associated type <hask>Elem ce</hask>.<br />
<br />
=== An Instance ===<br />
<br />
TODO<br />
<br />
<br />
== Open Issues ==<br />
<br />
None.</div>Tschrijvershttps://wiki.haskell.org/index.php?title=GHC/Type_families&diff=13207GHC/Type families2007-05-24T16:56:17Z<p>Tschrijvers: </p>
<hr />
<div>[[Category:GHC|Indexed types]]<br />
== Data and type families in GHC ==<br />
<br />
Data and type families are a new addition to GHC's type extensions. They are currently an '''experimental''' feature and so their design may still change to some degree. The current implementation covers ''data families'' (including newtypes), which can either be on the toplevel or inside class declarations - the latter are also known as [http://www.cse.unsw.edu.au/~chak/papers/CKPM05.html associated data types]. <br />
<br />
'''NB:''' Please note that type families (and hence also associated type synonyms) are '''not''' fully implemented yet. Any attempt to use them will lead to strange error messages. For the moment, you can only use <hask>data</hask> families.<br />
<br />
== What do I need to use data families? ==<br />
<br />
Indexed type families are implemented in GHC's HEAD (from version 6.7), which you can obtain in binary form from the [http://www.haskell.org/ghc/dist/current/dist/ nightly snapshots] or in source form from the [http://hackage.haskell.org/trac/ghc/wiki/Building/GettingTheSources source repository]. To enable indexed type families in GHC 6.7, you need to supply the compiler option <tt>-ftype-families</tt> (or <tt>-fglasgow-exts</tt>, which implies it). NB: The option used to be called <tt>-findexed-types</tt> for a while.<br />
<br />
== An associated data type example ==<br />
<br />
As an example, consider Ralf Hinze's [http://www.informatik.uni-bonn.de/~ralf/publications.html#J4 generalised tries], a form of generic finite maps. <br />
<br />
=== The class declaration ===<br />
<br />
We define a type class whose instances are the types that we can use as keys in our generic maps:<br />
<haskell><br />
class GMapKey k where<br />
data GMap k :: * -> *<br />
empty :: GMap k v<br />
lookup :: k -> GMap k v -> Maybe v<br />
insert :: k -> v -> GMap k v -> GMap k v<br />
</haskell><br />
The interesting part is the ''associated data family'' declaration of the class. It gives a [http://www.haskell.org/ghc/docs/latest/html/users_guide/type-extensions.html#sec-kinding ''kind signature''] (here <hask>* -> *</hask>) for the associated data type <hask>GMap k</hask> - analog to how methods receive a type signature in a class declaration.<br />
<br />
What it is important to notice is that the first parameter of the associated type <hask>GMap</hask> coincides with the class parameter of <hask>GMapKey</hask>. This indicates that also in all instances of the class, the instances of the associated data type need to have their first argument match up with the instance type. In general, the type arguments of an associated type can be a subset of the class parameters (in a multi-parameter type class) and they can appear in any order, possibly in an order other than in the class head. The latter can be useful if the associated data type is partially applied in some contexts.<br />
<br />
The second important point is that as <hask>GMap k</hask> has kind <hask>* -> *</hask> and <hask>k</hask> (implicitly) has kind <hask>*</hask>, the type constructor <hask>GMap</hask> (without an argument) has kind <hask>* -> * -> *</hask>. Consequently, we see that <hask>GMap</hask> is applied to two arguments in the signatures of the methods <hask>empty</hask>, <hask>lookup</hask>, and <hask>insert</hask>.<br />
<br />
=== An Int instance ===<br />
<br />
To use Ints as keys into generic maps, we declare an instance that simply uses <hask>Data.Map</hask>, thusly:<br />
<haskell><br />
instance GMapKey Int where<br />
data GMap Int v = GMapInt (Data.Map.Map Int v)<br />
empty = GMapInt Data.Map.empty<br />
lookup k (GMapInt m) = Data.Map.lookup k m<br />
insert k v (GMapInt m) = GMapInt (Data.Map.insert k v m)<br />
</haskell><br />
The <hask>Int</hask> instance of the associated data type <hask>GMap</hask> needs to have both of its parameters, but as only the first one corresponds to a class parameter, the second needs to be a type variable (here <hask>v</hask>). As mentioned before any associated type parameter that corresponds to a class parameter must be identical to the class parameter in each instance. The right hand side of the associated data declaration is like that of any other data type.<br />
<br />
NB: At the moment, GADT syntax is not allowed for associated data types (or other indexed types). This is not a fundemental limitation, but just a shortcoming of the current implementation, which we expect to lift in the future.<br />
<br />
As an exercise, implement an instance for <hask>Char</hask> that maps back to the <hask>Int</hask> instance using the conversion functions <hask>Char.ord</hask> and <hask>Char.chr</hask>.<br />
<br />
=== A unit instance ===<br />
<br />
Generic definitions, apart from elementary types, typically cover units, products, and sums. We start here with the unit instance for <hask>GMap</hask>:<br />
<haskell><br />
instance GMapKey () where<br />
data GMap () v = GMapUnit (Maybe v)<br />
empty = GMapUnit Nothing<br />
lookup () (GMapUnit v) = v<br />
insert () v (GMapUnit _) = GMapUnit $ Just v<br />
</haskell><br />
For unit, the map is just a <hask>Maybe</hask> value.<br />
<br />
=== Product and sum instances ===<br />
<br />
Nest, let us define the instances for pairs and sums (i.e., <hask>Either</hask>):<br />
<haskell><br />
instance (GMapKey a, GMapKey b) => GMapKey (a, b) where<br />
data GMap (a, b) v = GMapPair (GMap a (GMap b v))<br />
empty = GMapPair empty<br />
lookup (a, b) (GMapPair gm) = lookup a gm >>= lookup b <br />
insert (a, b) v (GMapPair gm) = GMapPair $ case lookup a gm of<br />
Nothing -> insert a (insert b v empty) gm<br />
Just gm2 -> insert a (insert b v gm2 ) gm<br />
<br />
instance (GMapKey a, GMapKey b) => GMapKey (Either a b) where<br />
data GMap (Either a b) v = GMapEither (GMap a v) (GMap b v)<br />
empty = GMapEither empty empty<br />
lookup (Left a) (GMapEither gm1 _gm2) = lookup a gm1<br />
lookup (Right b) (GMapEither _gm1 gm2 ) = lookup b gm2<br />
insert (Left a) v (GMapEither gm1 gm2) = GMapEither (insert a v gm1) gm2<br />
insert (Right a) v (GMapEither gm1 gm2) = GMapEither gm1 (insert a v gm2)<br />
</haskell><br />
If you find this code algorithmically surprising, I'd suggest to have a look at [http://www.informatik.uni-bonn.de/~ralf/publications.html#J4 Ralf Hinze's paper]. The only novelty concerning associated types, in these two instances, is that the instances have a context <hask>(GMapKey a, GMapKey b)</hask>. Consequently, the right hand sides of the associated type declarations can use <hask>GMap</hask> recursively at the key types <hask>a</hask> and <hask>b</hask> - not unlike the method definitions use the class methods recursively at the types for which the class is given in the instance context.<br />
<br />
=== Using a generic map ===<br />
<br />
Finally, some code building and quering a generic map:<br />
<haskell><br />
myGMap :: GMap (Int, Either Char ()) String<br />
myGMap = insert (5, Left 'c') "(5, Left 'c')" $<br />
insert (4, Right ()) "(4, Right ())" $<br />
insert (5, Right ()) "This is the one!" $<br />
insert (5, Right ()) "This is the two!" $<br />
insert (6, Right ()) "(6, Right ())" $<br />
insert (5, Left 'a') "(5, Left 'a')" $<br />
empty<br />
main = putStrLn $ maybe "Couldn't find key!" id $ lookup (5, Right ()) myGMap<br />
</haskell><br />
<br />
=== Download the code ===<br />
<br />
If you want to play with this example without copying it off the wiki, just download the [http://darcs.haskell.org/testsuite/tests/ghc-regress/indexed-types/should_run/GMapAssoc.hs source code for <hask>GMap</hask>] from GHC's test suite.<br />
<br />
== Definition of the type system extension ==<br />
<br />
['''NB:''' The following material will eventually become documentation for type families in the GHC User Manual. Please help to improve it by forwarding suggestions to <tt>chak@cse.unsw.edu.au</tt>.]<br />
<br />
Data families appear in two flavours: (1) they can be defined on the toplevel or (2) they can appear inside type classes (in which case they are known as associated types). The former is the more general variant, as it lacks the requirement for the type-indexes to coincide with the class parameters. However, the later can lead to more clearly structured code and compiler warnings if some type instances were - possibly accidentally - omitted. In the following, we always discuss the general toplevel form first and then cover the additional constraints placed on associated types.<br />
<br />
=== Family declarations ===<br />
<br />
Indexed data families are introduced by a signature, such as <br />
<haskell><br />
data family GMap k :: * -> *<br />
</haskell><br />
The special <hask>family</hask> distinguishes family from standard data declarations. The result kind annotation is optional and, as usual, defaults to <hask>*</hask> if omitted. An example is<br />
<haskell><br />
data family Array e<br />
</haskell><br />
Named arguments can also be given explicit kind signatures if needed. Just as with [http://www.haskell.org/ghc/docs/latest/html/users_guide/gadt.html GADT declarations] named arguments are entirely optional, so that we can declare <hask>Array</hask> alternatively with<br />
<haskell><br />
data family Array :: * -> *<br />
</haskell><br />
<br />
==== Associated family declarations ====<br />
<br />
When a data family is declared as part of a type class, we drop the <hask>family</hask> special. The <hask>GMap</hask> declaration takes the following form<br />
<haskell><br />
class GMapKey k where<br />
data GMap k :: * -> *<br />
...<br />
</haskell><br />
In contrast to toplevel declarations, named arguments must be used for all type parameters that are to be used as type-indexes. Moreover, the argument names must be class parameters. Each class parameter may only be used at most once per associated type, but some may be omitted and they may be in an order other than in the class head. Hence, the following contrieved example is admissible:<br />
<haskell><br />
class C a b c where<br />
data T c a :: *<br />
</haskell><br />
If kind signatures are required for argument variables, they need to be given in the class head.<br />
<br />
=== Instance declarations ===<br />
<br />
Instance declarations of data and newtype families are very similar to standard data and newtype declarations. The only two differences are that the keyword <hask>data</hask> or <hask>newtype</hask> is followed by <hask>instance</hask> and that some or all of the type arguments can be non-variable types. For example, the <hask>Either</hask> instance for <hask>GMap</hask> is<br />
<haskell><br />
data instance GMap (Either a b) v = GMapEither (GMap a v) (GMap b v)<br />
</haskell><br />
In this example, the declaration has only one variant. In general, it can be be any number.<br />
<br />
Data and newtype instance declarations are only legit when an appropriate family declaration is in scope - just like class instances require the class declaration to be visible. Moreover, each instance declaration has to conform to the kind determined by its family declaration. This implies that the number of parameters of an instance declaration matches the arity determined by the kind of the family. Although, all data families are declared with the <hask>data</hask> keyword, instances can be either <hask>data</hask> or <hask>newtype</hask>s, or a mix of both.<br />
<br />
Even if type families are defined as toplevel declarations, functions that perform different computations for different family instances still need to be defined as methods of type classes. In particular, the following is not possible:<br />
<haskell><br />
data family T a<br />
data instance T Int = A<br />
data instance T Char = B<br />
nonsence :: T a -> Int<br />
nonsence A = 1 -- WRONG: These two equations together...<br />
nonsence B = 2 -- ...will produce a type error.<br />
</haskell><br />
Given the functionality provided by GADTs (Generalised Algebraic Data Types), it might seem as if a definition, such as the above, should be feasible. However, type families are - in contrast to GADTs - are ''open''; i.e., new instances can always be added, possibly in other modules. Supporting pattern matching across different data instances would require a form of extensible case construct.<br />
<br />
==== Associated type instances ====<br />
<br />
When an associated family instance is declared within a type class instance, we drop the <hask>instance</hask> keyword in the family instance. So, the <hask>Either</hask> instance for <hask>GMap</hask> becomes:<br />
<haskell><br />
instance (GMapKey a, GMapKey b) => GMapKey (Either a b) where<br />
data GMap (Either a b) v = GMapEither (GMap a v) (GMap b v<br />
...<br />
</haskell><br />
The most important point about associated family instances is that the type indexes corresponding to class parameters must be identical to the type given in the instance head; here this is first argument of <hask>GMap</hask>, namely <hask>Either a b</hask>, which coincides with the only class parameter. Any parameters to the family constructor that do not correspond to class parameters, need to be variables in every instance; here this is the variable <hask>v</hask>.<br />
<br />
Instances for an associated family can only appear as part of instances declarations of the class in which the family was declared - just as with the equations of the methods of a class. Also in correspondence to how methods are handled, declarations of associated types can be omitted in class instances. If an associated family instance is omitted, the corresponding instance type is not inhabited; i.e., only diverging expressions, such as <hask>undefined</hask>, can assume the type.<br />
<br />
==== Class instances of type instances ====<br />
<br />
Type class instances of instances of data families can be defined as usual, and in particular data instance declarations can have <hask>deriving</hask> clauses. For example, we can write<br />
<haskell><br />
data GMap () v = GMapUnit (Maybe v)<br />
deriving Show<br />
</haskell><br />
which implcitly defines an instance of the form<br />
<haskell><br />
instance Show v => Show (GMap () v) where ...<br />
</haskell><br />
<br />
Note that class instances are always for particular ''instances'' of a data family and never for an entire family as a whole. This for essentially the same reasons that we cannot define a toplevel function that performs pattern matching on the data constructors of ''different'' instances of a single type family. It would require a form of extensible case construct.<br />
<br />
==== Overlap ====<br />
<br />
The instance declarations of a data family used in a single program may not overlap at all, independent of whether they are associated or not. In contrast to type class instances, this is not only a matter of consistency, but one of type safety.<br />
<br />
=== Import and export ===<br />
<br />
The association of data constructors with type families is more dynamic than that is the case with standard data and newtype declarations. In the standard case, the notation <hask>T(..)</hask> in an import or export list denotes the type constructor and all the data constructors introduced in its declaration. However, a family declaration never introduces any data constructors; instead, data constructors are introduced by family instances. As a result, which data constructors are associated with a type family depends on the currently visible instance declarations for that family. Consequently, an import or export item of the form <hask>T(..)</hask> denotes the family constructor and all currently visible data constructors - in the case of an export item, these may be either imported or defined in the current module. The treatment of import and export items that explicitly list data constructors, such as <hask>GMap(GMapEither)</hask>, is analogous.<br />
<br />
==== Associated families ====<br />
<br />
As expected, an import or export item of the form <hask>C(..)</hask> denotes all of the class' methods and associated types. However, when associated types are explicitly listed as subitems of a class, we need some new syntax, as uppercase identifiers as subitems are usually data constructors, not type constructors. To clarify that we denote types here, each associated type name needs to be prefixed by the keyword <hask>type</hask>. So for example, when explicitly listing the components of the <hask>GMapKey</hask> class, we write <hask>GMapKey(type GMap, empty, lookup, insert)</hask>.<br />
<br />
==== Examples ====<br />
<br />
Assuming our running <hask>GMapKey</hask> class example, let us look at some export lists and their meaning:<br />
<br />
* <hask>module GMap (GMapKey) where...</hask>: Exports just the class name.<br />
* <hask>module GMap (GMapKey(..)) where...</hask>: Exports the class, the associated type <hask>GMap</hask> and the member functions <hask>empty</hask>, <hask>lookup</hask>, and <hask>insert</hask>. None of the data constructors is exported.<br />
* <hask>module GMap (GMapKey(..), GMap(..)) where...</hask>: As before, but also exports all the data constructors <hask>GMapInt</hask>, <hask>GMapChar</hask>, <hask>GMapUnit</hask>, <hask>GMapPair</hask>, and <hask>GMapUnit</hask>.<br />
* <hask>module GMap (GMapKey(empty, lookup, insert), GMap(..)) where...</hask>: As before.<br />
* <hask>module GMap (GMapKey, empty, lookup, insert, GMap(..)) where...</hask>: As before.<br />
<br />
Finally, you can write <hask>GMapKey(type GMap)</hask> to denote both the class <hask>GMapKey</hask> as well as its associated type <hask>GMap</hask>. However, you cannot write <hask>GMapKey(type GMap(..))</hask> &mdash; i.e., sub-component specifications cannot be nested. To specify <hask>GMap</hask>'s data constructors, you have to list it separately.<br />
<br />
==== Instances ====<br />
<br />
Family instances are implicitly exported, just like class instances. However, this applies only to the heads of instances, not to the data constructors an instance defines.<br />
<br />
<br />
== A associated type synonym example ==<br />
<br />
Associated data types are a better alternative for the rather complicated<br />
functional dependencies.<br />
<br />
Here's an example from the original Functional Dependencies paper:<br />
<haskell><br />
class Collects e ce | ce -> e where<br />
empty :: ce<br />
insert :: e -> ce -> ce<br />
member :: e -> ce -> Bool<br />
</haskell><br />
<br />
With associated type synonyms we can write this as:<br />
<haskell><br />
class Collects ce where<br />
type Elem ce<br />
empty :: ce<br />
insert :: Elem ce -> ce -> ce<br />
member :: Elem ce -> ce -> Bool<br />
</haskell><br />
That's right, we have dropped from a multi-paramter type class<br />
to a single parameter type class. The parameter <hask>e</hask><br />
has become an associated type <hask>Elem ce</hask>.<br />
<br />
== Open Issues ==<br />
<br />
None.</hask></div>Tschrijvershttps://wiki.haskell.org/index.php?title=GHC/Type_families&diff=13206GHC/Type families2007-05-24T16:55:52Z<p>Tschrijvers: </p>
<hr />
<div>[[Category:GHC|Indexed types]]<br />
== Data and type families in GHC ==<br />
<br />
Data and type families are a new addition to GHC's type extensions. They are currently an '''experimental''' feature and so their design may still change to some degree. The current implementation covers ''data families'' (including newtypes), which can either be on the toplevel or inside class declarations - the latter are also known as [http://www.cse.unsw.edu.au/~chak/papers/CKPM05.html associated data types]. <br />
<br />
'''NB:''' Please note that type families (and hence also associated type synonyms) are '''not''' fully implemented yet. Any attempt to use them will lead to strange error messages. For the moment, you can only use <hask>data</hask> families.<br />
<br />
== What do I need to use data families? ==<br />
<br />
Indexed type families are implemented in GHC's HEAD (from version 6.7), which you can obtain in binary form from the [http://www.haskell.org/ghc/dist/current/dist/ nightly snapshots] or in source form from the [http://hackage.haskell.org/trac/ghc/wiki/Building/GettingTheSources source repository]. To enable indexed type families in GHC 6.7, you need to supply the compiler option <tt>-ftype-families</tt> (or <tt>-fglasgow-exts</tt>, which implies it). NB: The option used to be called <tt>-findexed-types</tt> for a while.<br />
<br />
== An associated data type example ==<br />
<br />
As an example, consider Ralf Hinze's [http://www.informatik.uni-bonn.de/~ralf/publications.html#J4 generalised tries], a form of generic finite maps. <br />
<br />
=== The class declaration ===<br />
<br />
We define a type class whose instances are the types that we can use as keys in our generic maps:<br />
<haskell><br />
class GMapKey k where<br />
data GMap k :: * -> *<br />
empty :: GMap k v<br />
lookup :: k -> GMap k v -> Maybe v<br />
insert :: k -> v -> GMap k v -> GMap k v<br />
</haskell><br />
The interesting part is the ''associated data family'' declaration of the class. It gives a [http://www.haskell.org/ghc/docs/latest/html/users_guide/type-extensions.html#sec-kinding ''kind signature''] (here <hask>* -> *</hask>) for the associated data type <hask>GMap k</hask> - analog to how methods receive a type signature in a class declaration.<br />
<br />
What it is important to notice is that the first parameter of the associated type <hask>GMap</hask> coincides with the class parameter of <hask>GMapKey</hask>. This indicates that also in all instances of the class, the instances of the associated data type need to have their first argument match up with the instance type. In general, the type arguments of an associated type can be a subset of the class parameters (in a multi-parameter type class) and they can appear in any order, possibly in an order other than in the class head. The latter can be useful if the associated data type is partially applied in some contexts.<br />
<br />
The second important point is that as <hask>GMap k</hask> has kind <hask>* -> *</hask> and <hask>k</hask> (implicitly) has kind <hask>*</hask>, the type constructor <hask>GMap</hask> (without an argument) has kind <hask>* -> * -> *</hask>. Consequently, we see that <hask>GMap</hask> is applied to two arguments in the signatures of the methods <hask>empty</hask>, <hask>lookup</hask>, and <hask>insert</hask>.<br />
<br />
=== An Int instance ===<br />
<br />
To use Ints as keys into generic maps, we declare an instance that simply uses <hask>Data.Map</hask>, thusly:<br />
<haskell><br />
instance GMapKey Int where<br />
data GMap Int v = GMapInt (Data.Map.Map Int v)<br />
empty = GMapInt Data.Map.empty<br />
lookup k (GMapInt m) = Data.Map.lookup k m<br />
insert k v (GMapInt m) = GMapInt (Data.Map.insert k v m)<br />
</haskell><br />
The <hask>Int</hask> instance of the associated data type <hask>GMap</hask> needs to have both of its parameters, but as only the first one corresponds to a class parameter, the second needs to be a type variable (here <hask>v</hask>). As mentioned before any associated type parameter that corresponds to a class parameter must be identical to the class parameter in each instance. The right hand side of the associated data declaration is like that of any other data type.<br />
<br />
NB: At the moment, GADT syntax is not allowed for associated data types (or other indexed types). This is not a fundemental limitation, but just a shortcoming of the current implementation, which we expect to lift in the future.<br />
<br />
As an exercise, implement an instance for <hask>Char</hask> that maps back to the <hask>Int</hask> instance using the conversion functions <hask>Char.ord</hask> and <hask>Char.chr</hask>.<br />
<br />
=== A unit instance ===<br />
<br />
Generic definitions, apart from elementary types, typically cover units, products, and sums. We start here with the unit instance for <hask>GMap</hask>:<br />
<haskell><br />
instance GMapKey () where<br />
data GMap () v = GMapUnit (Maybe v)<br />
empty = GMapUnit Nothing<br />
lookup () (GMapUnit v) = v<br />
insert () v (GMapUnit _) = GMapUnit $ Just v<br />
</haskell><br />
For unit, the map is just a <hask>Maybe</hask> value.<br />
<br />
=== Product and sum instances ===<br />
<br />
Nest, let us define the instances for pairs and sums (i.e., <hask>Either</hask>):<br />
<haskell><br />
instance (GMapKey a, GMapKey b) => GMapKey (a, b) where<br />
data GMap (a, b) v = GMapPair (GMap a (GMap b v))<br />
empty = GMapPair empty<br />
lookup (a, b) (GMapPair gm) = lookup a gm >>= lookup b <br />
insert (a, b) v (GMapPair gm) = GMapPair $ case lookup a gm of<br />
Nothing -> insert a (insert b v empty) gm<br />
Just gm2 -> insert a (insert b v gm2 ) gm<br />
<br />
instance (GMapKey a, GMapKey b) => GMapKey (Either a b) where<br />
data GMap (Either a b) v = GMapEither (GMap a v) (GMap b v)<br />
empty = GMapEither empty empty<br />
lookup (Left a) (GMapEither gm1 _gm2) = lookup a gm1<br />
lookup (Right b) (GMapEither _gm1 gm2 ) = lookup b gm2<br />
insert (Left a) v (GMapEither gm1 gm2) = GMapEither (insert a v gm1) gm2<br />
insert (Right a) v (GMapEither gm1 gm2) = GMapEither gm1 (insert a v gm2)<br />
</haskell><br />
If you find this code algorithmically surprising, I'd suggest to have a look at [http://www.informatik.uni-bonn.de/~ralf/publications.html#J4 Ralf Hinze's paper]. The only novelty concerning associated types, in these two instances, is that the instances have a context <hask>(GMapKey a, GMapKey b)</hask>. Consequently, the right hand sides of the associated type declarations can use <hask>GMap</hask> recursively at the key types <hask>a</hask> and <hask>b</hask> - not unlike the method definitions use the class methods recursively at the types for which the class is given in the instance context.<br />
<br />
=== Using a generic map ===<br />
<br />
Finally, some code building and quering a generic map:<br />
<haskell><br />
myGMap :: GMap (Int, Either Char ()) String<br />
myGMap = insert (5, Left 'c') "(5, Left 'c')" $<br />
insert (4, Right ()) "(4, Right ())" $<br />
insert (5, Right ()) "This is the one!" $<br />
insert (5, Right ()) "This is the two!" $<br />
insert (6, Right ()) "(6, Right ())" $<br />
insert (5, Left 'a') "(5, Left 'a')" $<br />
empty<br />
main = putStrLn $ maybe "Couldn't find key!" id $ lookup (5, Right ()) myGMap<br />
</haskell><br />
<br />
=== Download the code ===<br />
<br />
If you want to play with this example without copying it off the wiki, just download the [http://darcs.haskell.org/testsuite/tests/ghc-regress/indexed-types/should_run/GMapAssoc.hs source code for <hask>GMap</hask>] from GHC's test suite.<br />
<br />
== Definition of the type system extension ==<br />
<br />
['''NB:''' The following material will eventually become documentation for type families in the GHC User Manual. Please help to improve it by forwarding suggestions to <tt>chak@cse.unsw.edu.au</tt>.]<br />
<br />
Data families appear in two flavours: (1) they can be defined on the toplevel or (2) they can appear inside type classes (in which case they are known as associated types). The former is the more general variant, as it lacks the requirement for the type-indexes to coincide with the class parameters. However, the later can lead to more clearly structured code and compiler warnings if some type instances were - possibly accidentally - omitted. In the following, we always discuss the general toplevel form first and then cover the additional constraints placed on associated types.<br />
<br />
=== Family declarations ===<br />
<br />
Indexed data families are introduced by a signature, such as <br />
<haskell><br />
data family GMap k :: * -> *<br />
</haskell><br />
The special <hask>family</hask> distinguishes family from standard data declarations. The result kind annotation is optional and, as usual, defaults to <hask>*</hask> if omitted. An example is<br />
<haskell><br />
data family Array e<br />
</haskell><br />
Named arguments can also be given explicit kind signatures if needed. Just as with [http://www.haskell.org/ghc/docs/latest/html/users_guide/gadt.html GADT declarations] named arguments are entirely optional, so that we can declare <hask>Array</hask> alternatively with<br />
<haskell><br />
data family Array :: * -> *<br />
</haskell><br />
<br />
==== Associated family declarations ====<br />
<br />
When a data family is declared as part of a type class, we drop the <hask>family</hask> special. The <hask>GMap</hask> declaration takes the following form<br />
<haskell><br />
class GMapKey k where<br />
data GMap k :: * -> *<br />
...<br />
</haskell><br />
In contrast to toplevel declarations, named arguments must be used for all type parameters that are to be used as type-indexes. Moreover, the argument names must be class parameters. Each class parameter may only be used at most once per associated type, but some may be omitted and they may be in an order other than in the class head. Hence, the following contrieved example is admissible:<br />
<haskell><br />
class C a b c where<br />
data T c a :: *<br />
</haskell><br />
If kind signatures are required for argument variables, they need to be given in the class head.<br />
<br />
=== Instance declarations ===<br />
<br />
Instance declarations of data and newtype families are very similar to standard data and newtype declarations. The only two differences are that the keyword <hask>data</hask> or <hask>newtype</hask> is followed by <hask>instance</hask> and that some or all of the type arguments can be non-variable types. For example, the <hask>Either</hask> instance for <hask>GMap</hask> is<br />
<haskell><br />
data instance GMap (Either a b) v = GMapEither (GMap a v) (GMap b v)<br />
</haskell><br />
In this example, the declaration has only one variant. In general, it can be be any number.<br />
<br />
Data and newtype instance declarations are only legit when an appropriate family declaration is in scope - just like class instances require the class declaration to be visible. Moreover, each instance declaration has to conform to the kind determined by its family declaration. This implies that the number of parameters of an instance declaration matches the arity determined by the kind of the family. Although, all data families are declared with the <hask>data</hask> keyword, instances can be either <hask>data</hask> or <hask>newtype</hask>s, or a mix of both.<br />
<br />
Even if type families are defined as toplevel declarations, functions that perform different computations for different family instances still need to be defined as methods of type classes. In particular, the following is not possible:<br />
<haskell><br />
data family T a<br />
data instance T Int = A<br />
data instance T Char = B<br />
nonsence :: T a -> Int<br />
nonsence A = 1 -- WRONG: These two equations together...<br />
nonsence B = 2 -- ...will produce a type error.<br />
</haskell><br />
Given the functionality provided by GADTs (Generalised Algebraic Data Types), it might seem as if a definition, such as the above, should be feasible. However, type families are - in contrast to GADTs - are ''open''; i.e., new instances can always be added, possibly in other modules. Supporting pattern matching across different data instances would require a form of extensible case construct.<br />
<br />
==== Associated type instances ====<br />
<br />
When an associated family instance is declared within a type class instance, we drop the <hask>instance</hask> keyword in the family instance. So, the <hask>Either</hask> instance for <hask>GMap</hask> becomes:<br />
<haskell><br />
instance (GMapKey a, GMapKey b) => GMapKey (Either a b) where<br />
data GMap (Either a b) v = GMapEither (GMap a v) (GMap b v<br />
...<br />
</haskell><br />
The most important point about associated family instances is that the type indexes corresponding to class parameters must be identical to the type given in the instance head; here this is first argument of <hask>GMap</hask>, namely <hask>Either a b</hask>, which coincides with the only class parameter. Any parameters to the family constructor that do not correspond to class parameters, need to be variables in every instance; here this is the variable <hask>v</hask>.<br />
<br />
Instances for an associated family can only appear as part of instances declarations of the class in which the family was declared - just as with the equations of the methods of a class. Also in correspondence to how methods are handled, declarations of associated types can be omitted in class instances. If an associated family instance is omitted, the corresponding instance type is not inhabited; i.e., only diverging expressions, such as <hask>undefined</hask>, can assume the type.<br />
<br />
==== Class instances of type instances ====<br />
<br />
Type class instances of instances of data families can be defined as usual, and in particular data instance declarations can have <hask>deriving</hask> clauses. For example, we can write<br />
<haskell><br />
data GMap () v = GMapUnit (Maybe v)<br />
deriving Show<br />
</haskell><br />
which implcitly defines an instance of the form<br />
<haskell><br />
instance Show v => Show (GMap () v) where ...<br />
</haskell><br />
<br />
Note that class instances are always for particular ''instances'' of a data family and never for an entire family as a whole. This for essentially the same reasons that we cannot define a toplevel function that performs pattern matching on the data constructors of ''different'' instances of a single type family. It would require a form of extensible case construct.<br />
<br />
==== Overlap ====<br />
<br />
The instance declarations of a data family used in a single program may not overlap at all, independent of whether they are associated or not. In contrast to type class instances, this is not only a matter of consistency, but one of type safety.<br />
<br />
=== Import and export ===<br />
<br />
The association of data constructors with type families is more dynamic than that is the case with standard data and newtype declarations. In the standard case, the notation <hask>T(..)</hask> in an import or export list denotes the type constructor and all the data constructors introduced in its declaration. However, a family declaration never introduces any data constructors; instead, data constructors are introduced by family instances. As a result, which data constructors are associated with a type family depends on the currently visible instance declarations for that family. Consequently, an import or export item of the form <hask>T(..)</hask> denotes the family constructor and all currently visible data constructors - in the case of an export item, these may be either imported or defined in the current module. The treatment of import and export items that explicitly list data constructors, such as <hask>GMap(GMapEither)</hask>, is analogous.<br />
<br />
==== Associated families ====<br />
<br />
As expected, an import or export item of the form <hask>C(..)</hask> denotes all of the class' methods and associated types. However, when associated types are explicitly listed as subitems of a class, we need some new syntax, as uppercase identifiers as subitems are usually data constructors, not type constructors. To clarify that we denote types here, each associated type name needs to be prefixed by the keyword <hask>type</hask>. So for example, when explicitly listing the components of the <hask>GMapKey</hask> class, we write <hask>GMapKey(type GMap, empty, lookup, insert)</hask>.<br />
<br />
==== Examples ====<br />
<br />
Assuming our running <hask>GMapKey</hask> class example, let us look at some export lists and their meaning:<br />
<br />
* <hask>module GMap (GMapKey) where...</hask>: Exports just the class name.<br />
* <hask>module GMap (GMapKey(..)) where...</hask>: Exports the class, the associated type <hask>GMap</hask> and the member functions <hask>empty</hask>, <hask>lookup</hask>, and <hask>insert</hask>. None of the data constructors is exported.<br />
* <hask>module GMap (GMapKey(..), GMap(..)) where...</hask>: As before, but also exports all the data constructors <hask>GMapInt</hask>, <hask>GMapChar</hask>, <hask>GMapUnit</hask>, <hask>GMapPair</hask>, and <hask>GMapUnit</hask>.<br />
* <hask>module GMap (GMapKey(empty, lookup, insert), GMap(..)) where...</hask>: As before.<br />
* <hask>module GMap (GMapKey, empty, lookup, insert, GMap(..)) where...</hask>: As before.<br />
<br />
Finally, you can write <hask>GMapKey(type GMap)</hask> to denote both the class <hask>GMapKey</hask> as well as its associated type <hask>GMap</hask>. However, you cannot write <hask>GMapKey(type GMap(..))</hask> &mdash; i.e., sub-component specifications cannot be nested. To specify <hask>GMap</hask>'s data constructors, you have to list it separately.<br />
<br />
==== Instances ====<br />
<br />
Family instances are implicitly exported, just like class instances. However, this applies only to the heads of instances, not to the data constructors an instance defines.<br />
<br />
<br />
== A associated type synonym example ==<br />
<br />
Associated data types are a better alternative for the rather complicated<br />
functional dependencies.<br />
<br />
Here's an example from the original Functional Dependencies paper:<br />
<haskell><br />
class Collects e ce | ce -> e where<br />
empty :: ce<br />
insert :: e -> ce -> ce<br />
member :: e -> ce -> Bool<br />
</haskell><br />
<br />
With associated type synonyms we can write this as:<br />
<haskell><br />
class Collects ce where<br />
type Elem ce<br />
empty :: ce<br />
insert :: Elem ce -> ce -> ce<br />
member :: Elem ce -> ce -> Bool<br />
</haskell><br />
That's right, we have dropped from a multi-paramter type class<br />
to a single parameter type class. The parameter <hask>e</hask><br />
has become an associated type <hask>Elem ce</e>.<br />
<br />
== Open Issues ==<br />
<br />
None.</hask></div>Tschrijvershttps://wiki.haskell.org/index.php?title=GHC/Type_families&diff=13205GHC/Type families2007-05-24T16:53:46Z<p>Tschrijvers: </p>
<hr />
<div>[[Category:GHC|Indexed types]]<br />
== Data and type families in GHC ==<br />
<br />
Data and type families are a new addition to GHC's type extensions. They are currently an '''experimental''' feature and so their design may still change to some degree. The current implementation covers ''data families'' (including newtypes), which can either be on the toplevel or inside class declarations - the latter are also known as [http://www.cse.unsw.edu.au/~chak/papers/CKPM05.html associated data types]. <br />
<br />
'''NB:''' Please note that type families (and hence also associated type synonyms) are '''not''' fully implemented yet. Any attempt to use them will lead to strange error messages. For the moment, you can only use <hask>data</hask> families.<br />
<br />
== What do I need to use data families? ==<br />
<br />
Indexed type families are implemented in GHC's HEAD (from version 6.7), which you can obtain in binary form from the [http://www.haskell.org/ghc/dist/current/dist/ nightly snapshots] or in source form from the [http://hackage.haskell.org/trac/ghc/wiki/Building/GettingTheSources source repository]. To enable indexed type families in GHC 6.7, you need to supply the compiler option <tt>-ftype-families</tt> (or <tt>-fglasgow-exts</tt>, which implies it). NB: The option used to be called <tt>-findexed-types</tt> for a while.<br />
<br />
== An associated data type example ==<br />
<br />
As an example, consider Ralf Hinze's [http://www.informatik.uni-bonn.de/~ralf/publications.html#J4 generalised tries], a form of generic finite maps. <br />
<br />
=== The class declaration ===<br />
<br />
We define a type class whose instances are the types that we can use as keys in our generic maps:<br />
<haskell><br />
class GMapKey k where<br />
data GMap k :: * -> *<br />
empty :: GMap k v<br />
lookup :: k -> GMap k v -> Maybe v<br />
insert :: k -> v -> GMap k v -> GMap k v<br />
</haskell><br />
The interesting part is the ''associated data family'' declaration of the class. It gives a [http://www.haskell.org/ghc/docs/latest/html/users_guide/type-extensions.html#sec-kinding ''kind signature''] (here <hask>* -> *</hask>) for the associated data type <hask>GMap k</hask> - analog to how methods receive a type signature in a class declaration.<br />
<br />
What it is important to notice is that the first parameter of the associated type <hask>GMap</hask> coincides with the class parameter of <hask>GMapKey</hask>. This indicates that also in all instances of the class, the instances of the associated data type need to have their first argument match up with the instance type. In general, the type arguments of an associated type can be a subset of the class parameters (in a multi-parameter type class) and they can appear in any order, possibly in an order other than in the class head. The latter can be useful if the associated data type is partially applied in some contexts.<br />
<br />
The second important point is that as <hask>GMap k</hask> has kind <hask>* -> *</hask> and <hask>k</hask> (implicitly) has kind <hask>*</hask>, the type constructor <hask>GMap</hask> (without an argument) has kind <hask>* -> * -> *</hask>. Consequently, we see that <hask>GMap</hask> is applied to two arguments in the signatures of the methods <hask>empty</hask>, <hask>lookup</hask>, and <hask>insert</hask>.<br />
<br />
=== An Int instance ===<br />
<br />
To use Ints as keys into generic maps, we declare an instance that simply uses <hask>Data.Map</hask>, thusly:<br />
<haskell><br />
instance GMapKey Int where<br />
data GMap Int v = GMapInt (Data.Map.Map Int v)<br />
empty = GMapInt Data.Map.empty<br />
lookup k (GMapInt m) = Data.Map.lookup k m<br />
insert k v (GMapInt m) = GMapInt (Data.Map.insert k v m)<br />
</haskell><br />
The <hask>Int</hask> instance of the associated data type <hask>GMap</hask> needs to have both of its parameters, but as only the first one corresponds to a class parameter, the second needs to be a type variable (here <hask>v</hask>). As mentioned before any associated type parameter that corresponds to a class parameter must be identical to the class parameter in each instance. The right hand side of the associated data declaration is like that of any other data type.<br />
<br />
NB: At the moment, GADT syntax is not allowed for associated data types (or other indexed types). This is not a fundemental limitation, but just a shortcoming of the current implementation, which we expect to lift in the future.<br />
<br />
As an exercise, implement an instance for <hask>Char</hask> that maps back to the <hask>Int</hask> instance using the conversion functions <hask>Char.ord</hask> and <hask>Char.chr</hask>.<br />
<br />
=== A unit instance ===<br />
<br />
Generic definitions, apart from elementary types, typically cover units, products, and sums. We start here with the unit instance for <hask>GMap</hask>:<br />
<haskell><br />
instance GMapKey () where<br />
data GMap () v = GMapUnit (Maybe v)<br />
empty = GMapUnit Nothing<br />
lookup () (GMapUnit v) = v<br />
insert () v (GMapUnit _) = GMapUnit $ Just v<br />
</haskell><br />
For unit, the map is just a <hask>Maybe</hask> value.<br />
<br />
=== Product and sum instances ===<br />
<br />
Nest, let us define the instances for pairs and sums (i.e., <hask>Either</hask>):<br />
<haskell><br />
instance (GMapKey a, GMapKey b) => GMapKey (a, b) where<br />
data GMap (a, b) v = GMapPair (GMap a (GMap b v))<br />
empty = GMapPair empty<br />
lookup (a, b) (GMapPair gm) = lookup a gm >>= lookup b <br />
insert (a, b) v (GMapPair gm) = GMapPair $ case lookup a gm of<br />
Nothing -> insert a (insert b v empty) gm<br />
Just gm2 -> insert a (insert b v gm2 ) gm<br />
<br />
instance (GMapKey a, GMapKey b) => GMapKey (Either a b) where<br />
data GMap (Either a b) v = GMapEither (GMap a v) (GMap b v)<br />
empty = GMapEither empty empty<br />
lookup (Left a) (GMapEither gm1 _gm2) = lookup a gm1<br />
lookup (Right b) (GMapEither _gm1 gm2 ) = lookup b gm2<br />
insert (Left a) v (GMapEither gm1 gm2) = GMapEither (insert a v gm1) gm2<br />
insert (Right a) v (GMapEither gm1 gm2) = GMapEither gm1 (insert a v gm2)<br />
</haskell><br />
If you find this code algorithmically surprising, I'd suggest to have a look at [http://www.informatik.uni-bonn.de/~ralf/publications.html#J4 Ralf Hinze's paper]. The only novelty concerning associated types, in these two instances, is that the instances have a context <hask>(GMapKey a, GMapKey b)</hask>. Consequently, the right hand sides of the associated type declarations can use <hask>GMap</hask> recursively at the key types <hask>a</hask> and <hask>b</hask> - not unlike the method definitions use the class methods recursively at the types for which the class is given in the instance context.<br />
<br />
=== Using a generic map ===<br />
<br />
Finally, some code building and quering a generic map:<br />
<haskell><br />
myGMap :: GMap (Int, Either Char ()) String<br />
myGMap = insert (5, Left 'c') "(5, Left 'c')" $<br />
insert (4, Right ()) "(4, Right ())" $<br />
insert (5, Right ()) "This is the one!" $<br />
insert (5, Right ()) "This is the two!" $<br />
insert (6, Right ()) "(6, Right ())" $<br />
insert (5, Left 'a') "(5, Left 'a')" $<br />
empty<br />
main = putStrLn $ maybe "Couldn't find key!" id $ lookup (5, Right ()) myGMap<br />
</haskell><br />
<br />
=== Download the code ===<br />
<br />
If you want to play with this example without copying it off the wiki, just download the [http://darcs.haskell.org/testsuite/tests/ghc-regress/indexed-types/should_run/GMapAssoc.hs source code for <hask>GMap</hask>] from GHC's test suite.<br />
<br />
== Definition of the type system extension ==<br />
<br />
['''NB:''' The following material will eventually become documentation for type families in the GHC User Manual. Please help to improve it by forwarding suggestions to <tt>chak@cse.unsw.edu.au</tt>.]<br />
<br />
Data families appear in two flavours: (1) they can be defined on the toplevel or (2) they can appear inside type classes (in which case they are known as associated types). The former is the more general variant, as it lacks the requirement for the type-indexes to coincide with the class parameters. However, the later can lead to more clearly structured code and compiler warnings if some type instances were - possibly accidentally - omitted. In the following, we always discuss the general toplevel form first and then cover the additional constraints placed on associated types.<br />
<br />
=== Family declarations ===<br />
<br />
Indexed data families are introduced by a signature, such as <br />
<haskell><br />
data family GMap k :: * -> *<br />
</haskell><br />
The special <hask>family</hask> distinguishes family from standard data declarations. The result kind annotation is optional and, as usual, defaults to <hask>*</hask> if omitted. An example is<br />
<haskell><br />
data family Array e<br />
</haskell><br />
Named arguments can also be given explicit kind signatures if needed. Just as with [http://www.haskell.org/ghc/docs/latest/html/users_guide/gadt.html GADT declarations] named arguments are entirely optional, so that we can declare <hask>Array</hask> alternatively with<br />
<haskell><br />
data family Array :: * -> *<br />
</haskell><br />
<br />
==== Associated family declarations ====<br />
<br />
When a data family is declared as part of a type class, we drop the <hask>family</hask> special. The <hask>GMap</hask> declaration takes the following form<br />
<haskell><br />
class GMapKey k where<br />
data GMap k :: * -> *<br />
...<br />
</haskell><br />
In contrast to toplevel declarations, named arguments must be used for all type parameters that are to be used as type-indexes. Moreover, the argument names must be class parameters. Each class parameter may only be used at most once per associated type, but some may be omitted and they may be in an order other than in the class head. Hence, the following contrieved example is admissible:<br />
<haskell><br />
class C a b c where<br />
data T c a :: *<br />
</haskell><br />
If kind signatures are required for argument variables, they need to be given in the class head.<br />
<br />
=== Instance declarations ===<br />
<br />
Instance declarations of data and newtype families are very similar to standard data and newtype declarations. The only two differences are that the keyword <hask>data</hask> or <hask>newtype</hask> is followed by <hask>instance</hask> and that some or all of the type arguments can be non-variable types. For example, the <hask>Either</hask> instance for <hask>GMap</hask> is<br />
<haskell><br />
data instance GMap (Either a b) v = GMapEither (GMap a v) (GMap b v)<br />
</haskell><br />
In this example, the declaration has only one variant. In general, it can be be any number.<br />
<br />
Data and newtype instance declarations are only legit when an appropriate family declaration is in scope - just like class instances require the class declaration to be visible. Moreover, each instance declaration has to conform to the kind determined by its family declaration. This implies that the number of parameters of an instance declaration matches the arity determined by the kind of the family. Although, all data families are declared with the <hask>data</hask> keyword, instances can be either <hask>data</hask> or <hask>newtype</hask>s, or a mix of both.<br />
<br />
Even if type families are defined as toplevel declarations, functions that perform different computations for different family instances still need to be defined as methods of type classes. In particular, the following is not possible:<br />
<haskell><br />
data family T a<br />
data instance T Int = A<br />
data instance T Char = B<br />
nonsence :: T a -> Int<br />
nonsence A = 1 -- WRONG: These two equations together...<br />
nonsence B = 2 -- ...will produce a type error.<br />
</haskell><br />
Given the functionality provided by GADTs (Generalised Algebraic Data Types), it might seem as if a definition, such as the above, should be feasible. However, type families are - in contrast to GADTs - are ''open''; i.e., new instances can always be added, possibly in other modules. Supporting pattern matching across different data instances would require a form of extensible case construct.<br />
<br />
==== Associated type instances ====<br />
<br />
When an associated family instance is declared within a type class instance, we drop the <hask>instance</hask> keyword in the family instance. So, the <hask>Either</hask> instance for <hask>GMap</hask> becomes:<br />
<haskell><br />
instance (GMapKey a, GMapKey b) => GMapKey (Either a b) where<br />
data GMap (Either a b) v = GMapEither (GMap a v) (GMap b v<br />
...<br />
</haskell><br />
The most important point about associated family instances is that the type indexes corresponding to class parameters must be identical to the type given in the instance head; here this is first argument of <hask>GMap</hask>, namely <hask>Either a b</hask>, which coincides with the only class parameter. Any parameters to the family constructor that do not correspond to class parameters, need to be variables in every instance; here this is the variable <hask>v</hask>.<br />
<br />
Instances for an associated family can only appear as part of instances declarations of the class in which the family was declared - just as with the equations of the methods of a class. Also in correspondence to how methods are handled, declarations of associated types can be omitted in class instances. If an associated family instance is omitted, the corresponding instance type is not inhabited; i.e., only diverging expressions, such as <hask>undefined</hask>, can assume the type.<br />
<br />
==== Class instances of type instances ====<br />
<br />
Type class instances of instances of data families can be defined as usual, and in particular data instance declarations can have <hask>deriving</hask> clauses. For example, we can write<br />
<haskell><br />
data GMap () v = GMapUnit (Maybe v)<br />
deriving Show<br />
</haskell><br />
which implcitly defines an instance of the form<br />
<haskell><br />
instance Show v => Show (GMap () v) where ...<br />
</haskell><br />
<br />
Note that class instances are always for particular ''instances'' of a data family and never for an entire family as a whole. This for essentially the same reasons that we cannot define a toplevel function that performs pattern matching on the data constructors of ''different'' instances of a single type family. It would require a form of extensible case construct.<br />
<br />
==== Overlap ====<br />
<br />
The instance declarations of a data family used in a single program may not overlap at all, independent of whether they are associated or not. In contrast to type class instances, this is not only a matter of consistency, but one of type safety.<br />
<br />
=== Import and export ===<br />
<br />
The association of data constructors with type families is more dynamic than that is the case with standard data and newtype declarations. In the standard case, the notation <hask>T(..)</hask> in an import or export list denotes the type constructor and all the data constructors introduced in its declaration. However, a family declaration never introduces any data constructors; instead, data constructors are introduced by family instances. As a result, which data constructors are associated with a type family depends on the currently visible instance declarations for that family. Consequently, an import or export item of the form <hask>T(..)</hask> denotes the family constructor and all currently visible data constructors - in the case of an export item, these may be either imported or defined in the current module. The treatment of import and export items that explicitly list data constructors, such as <hask>GMap(GMapEither)</hask>, is analogous.<br />
<br />
==== Associated families ====<br />
<br />
As expected, an import or export item of the form <hask>C(..)</hask> denotes all of the class' methods and associated types. However, when associated types are explicitly listed as subitems of a class, we need some new syntax, as uppercase identifiers as subitems are usually data constructors, not type constructors. To clarify that we denote types here, each associated type name needs to be prefixed by the keyword <hask>type</hask>. So for example, when explicitly listing the components of the <hask>GMapKey</hask> class, we write <hask>GMapKey(type GMap, empty, lookup, insert)</hask>.<br />
<br />
==== Examples ====<br />
<br />
Assuming our running <hask>GMapKey</hask> class example, let us look at some export lists and their meaning:<br />
<br />
* <hask>module GMap (GMapKey) where...</hask>: Exports just the class name.<br />
* <hask>module GMap (GMapKey(..)) where...</hask>: Exports the class, the associated type <hask>GMap</hask> and the member functions <hask>empty</hask>, <hask>lookup</hask>, and <hask>insert</hask>. None of the data constructors is exported.<br />
* <hask>module GMap (GMapKey(..), GMap(..)) where...</hask>: As before, but also exports all the data constructors <hask>GMapInt</hask>, <hask>GMapChar</hask>, <hask>GMapUnit</hask>, <hask>GMapPair</hask>, and <hask>GMapUnit</hask>.<br />
* <hask>module GMap (GMapKey(empty, lookup, insert), GMap(..)) where...</hask>: As before.<br />
* <hask>module GMap (GMapKey, empty, lookup, insert, GMap(..)) where...</hask>: As before.<br />
<br />
Finally, you can write <hask>GMapKey(type GMap)</hask> to denote both the class <hask>GMapKey</hask> as well as its associated type <hask>GMap</hask>. However, you cannot write <hask>GMapKey(type GMap(..))</hask> &mdash; i.e., sub-component specifications cannot be nested. To specify <hask>GMap</hask>'s data constructors, you have to list it separately.<br />
<br />
==== Instances ====<br />
<br />
Family instances are implicitly exported, just like class instances. However, this applies only to the heads of instances, not to the data constructors an instance defines.<br />
<br />
<br />
== A associated type synonym example ==<br />
<br />
Associated data types are a better alternative for the rather complicated<br />
functional dependencies.<br />
<br />
Here's an example from the original Functional Dependencies paper:<br />
<haskell><br />
class Collects e ce | ce -> e where<br />
empty :: ce<br />
insert :: e -> ce -> ce<br />
member :: e -> ce -> Bool<br />
</haskell><br />
<br />
== Open Issues ==<br />
<br />
None.</div>Tschrijvershttps://wiki.haskell.org/index.php?title=GHC/Type_families&diff=13204GHC/Type families2007-05-24T16:48:10Z<p>Tschrijvers: </p>
<hr />
<div>[[Category:GHC|Indexed types]]<br />
== Data and type families in GHC ==<br />
<br />
Data and type families are a new addition to GHC's type extensions. They are currently an '''experimental''' feature and so their design may still change to some degree. The current implementation covers ''data families'' (including newtypes), which can either be on the toplevel or inside class declarations - the latter are also known as [http://www.cse.unsw.edu.au/~chak/papers/CKPM05.html associated data types]. <br />
<br />
'''NB:''' Please note that type families (and hence also associated type synonyms) are '''not''' fully implemented yet. Any attempt to use them will lead to strange error messages. For the moment, you can only use <hask>data</hask> families.<br />
<br />
== What do I need to use data families? ==<br />
<br />
Indexed type families are implemented in GHC's HEAD (from version 6.7), which you can obtain in binary form from the [http://www.haskell.org/ghc/dist/current/dist/ nightly snapshots] or in source form from the [http://hackage.haskell.org/trac/ghc/wiki/Building/GettingTheSources source repository]. To enable indexed type families in GHC 6.7, you need to supply the compiler option <tt>-ftype-families</tt> (or <tt>-fglasgow-exts</tt>, which implies it). NB: The option used to be called <tt>-findexed-types</tt> for a while.<br />
<br />
== An associated data type example ==<br />
<br />
As an example, consider Ralf Hinze's [http://www.informatik.uni-bonn.de/~ralf/publications.html#J4 generalised tries], a form of generic finite maps. <br />
<br />
=== The class declaration ===<br />
<br />
We define a type class whose instances are the types that we can use as keys in our generic maps:<br />
<haskell><br />
class GMapKey k where<br />
data GMap k :: * -> *<br />
empty :: GMap k v<br />
lookup :: k -> GMap k v -> Maybe v<br />
insert :: k -> v -> GMap k v -> GMap k v<br />
</haskell><br />
The interesting part is the ''associated data family'' declaration of the class. It gives a [http://www.haskell.org/ghc/docs/latest/html/users_guide/type-extensions.html#sec-kinding ''kind signature''] (here <hask>* -> *</hask>) for the associated data type <hask>GMap k</hask> - analog to how methods receive a type signature in a class declaration.<br />
<br />
What it is important to notice is that the first parameter of the associated type <hask>GMap</hask> coincides with the class parameter of <hask>GMapKey</hask>. This indicates that also in all instances of the class, the instances of the associated data type need to have their first argument match up with the instance type. In general, the type arguments of an associated type can be a subset of the class parameters (in a multi-parameter type class) and they can appear in any order, possibly in an order other than in the class head. The latter can be useful if the associated data type is partially applied in some contexts.<br />
<br />
The second important point is that as <hask>GMap k</hask> has kind <hask>* -> *</hask> and <hask>k</hask> (implicitly) has kind <hask>*</hask>, the type constructor <hask>GMap</hask> (without an argument) has kind <hask>* -> * -> *</hask>. Consequently, we see that <hask>GMap</hask> is applied to two arguments in the signatures of the methods <hask>empty</hask>, <hask>lookup</hask>, and <hask>insert</hask>.<br />
<br />
=== An Int instance ===<br />
<br />
To use Ints as keys into generic maps, we declare an instance that simply uses <hask>Data.Map</hask>, thusly:<br />
<haskell><br />
instance GMapKey Int where<br />
data GMap Int v = GMapInt (Data.Map.Map Int v)<br />
empty = GMapInt Data.Map.empty<br />
lookup k (GMapInt m) = Data.Map.lookup k m<br />
insert k v (GMapInt m) = GMapInt (Data.Map.insert k v m)<br />
</haskell><br />
The <hask>Int</hask> instance of the associated data type <hask>GMap</hask> needs to have both of its parameters, but as only the first one corresponds to a class parameter, the second needs to be a type variable (here <hask>v</hask>). As mentioned before any associated type parameter that corresponds to a class parameter must be identical to the class parameter in each instance. The right hand side of the associated data declaration is like that of any other data type.<br />
<br />
NB: At the moment, GADT syntax is not allowed for associated data types (or other indexed types). This is not a fundemental limitation, but just a shortcoming of the current implementation, which we expect to lift in the future.<br />
<br />
As an exercise, implement an instance for <hask>Char</hask> that maps back to the <hask>Int</hask> instance using the conversion functions <hask>Char.ord</hask> and <hask>Char.chr</hask>.<br />
<br />
=== A unit instance ===<br />
<br />
Generic definitions, apart from elementary types, typically cover units, products, and sums. We start here with the unit instance for <hask>GMap</hask>:<br />
<haskell><br />
instance GMapKey () where<br />
data GMap () v = GMapUnit (Maybe v)<br />
empty = GMapUnit Nothing<br />
lookup () (GMapUnit v) = v<br />
insert () v (GMapUnit _) = GMapUnit $ Just v<br />
</haskell><br />
For unit, the map is just a <hask>Maybe</hask> value.<br />
<br />
=== Product and sum instances ===<br />
<br />
Nest, let us define the instances for pairs and sums (i.e., <hask>Either</hask>):<br />
<haskell><br />
instance (GMapKey a, GMapKey b) => GMapKey (a, b) where<br />
data GMap (a, b) v = GMapPair (GMap a (GMap b v))<br />
empty = GMapPair empty<br />
lookup (a, b) (GMapPair gm) = lookup a gm >>= lookup b <br />
insert (a, b) v (GMapPair gm) = GMapPair $ case lookup a gm of<br />
Nothing -> insert a (insert b v empty) gm<br />
Just gm2 -> insert a (insert b v gm2 ) gm<br />
<br />
instance (GMapKey a, GMapKey b) => GMapKey (Either a b) where<br />
data GMap (Either a b) v = GMapEither (GMap a v) (GMap b v)<br />
empty = GMapEither empty empty<br />
lookup (Left a) (GMapEither gm1 _gm2) = lookup a gm1<br />
lookup (Right b) (GMapEither _gm1 gm2 ) = lookup b gm2<br />
insert (Left a) v (GMapEither gm1 gm2) = GMapEither (insert a v gm1) gm2<br />
insert (Right a) v (GMapEither gm1 gm2) = GMapEither gm1 (insert a v gm2)<br />
</haskell><br />
If you find this code algorithmically surprising, I'd suggest to have a look at [http://www.informatik.uni-bonn.de/~ralf/publications.html#J4 Ralf Hinze's paper]. The only novelty concerning associated types, in these two instances, is that the instances have a context <hask>(GMapKey a, GMapKey b)</hask>. Consequently, the right hand sides of the associated type declarations can use <hask>GMap</hask> recursively at the key types <hask>a</hask> and <hask>b</hask> - not unlike the method definitions use the class methods recursively at the types for which the class is given in the instance context.<br />
<br />
=== Using a generic map ===<br />
<br />
Finally, some code building and quering a generic map:<br />
<haskell><br />
myGMap :: GMap (Int, Either Char ()) String<br />
myGMap = insert (5, Left 'c') "(5, Left 'c')" $<br />
insert (4, Right ()) "(4, Right ())" $<br />
insert (5, Right ()) "This is the one!" $<br />
insert (5, Right ()) "This is the two!" $<br />
insert (6, Right ()) "(6, Right ())" $<br />
insert (5, Left 'a') "(5, Left 'a')" $<br />
empty<br />
main = putStrLn $ maybe "Couldn't find key!" id $ lookup (5, Right ()) myGMap<br />
</haskell><br />
<br />
=== Download the code ===<br />
<br />
If you want to play with this example without copying it off the wiki, just download the [http://darcs.haskell.org/testsuite/tests/ghc-regress/indexed-types/should_run/GMapAssoc.hs source code for <hask>GMap</hask>] from GHC's test suite.<br />
<br />
== Definition of the type system extension ==<br />
<br />
['''NB:''' The following material will eventually become documentation for type families in the GHC User Manual. Please help to improve it by forwarding suggestions to <tt>chak@cse.unsw.edu.au</tt>.]<br />
<br />
Data families appear in two flavours: (1) they can be defined on the toplevel or (2) they can appear inside type classes (in which case they are known as associated types). The former is the more general variant, as it lacks the requirement for the type-indexes to coincide with the class parameters. However, the later can lead to more clearly structured code and compiler warnings if some type instances were - possibly accidentally - omitted. In the following, we always discuss the general toplevel form first and then cover the additional constraints placed on associated types.<br />
<br />
=== Family declarations ===<br />
<br />
Indexed data families are introduced by a signature, such as <br />
<haskell><br />
data family GMap k :: * -> *<br />
</haskell><br />
The special <hask>family</hask> distinguishes family from standard data declarations. The result kind annotation is optional and, as usual, defaults to <hask>*</hask> if omitted. An example is<br />
<haskell><br />
data family Array e<br />
</haskell><br />
Named arguments can also be given explicit kind signatures if needed. Just as with [http://www.haskell.org/ghc/docs/latest/html/users_guide/gadt.html GADT declarations] named arguments are entirely optional, so that we can declare <hask>Array</hask> alternatively with<br />
<haskell><br />
data family Array :: * -> *<br />
</haskell><br />
<br />
==== Associated family declarations ====<br />
<br />
When a data family is declared as part of a type class, we drop the <hask>family</hask> special. The <hask>GMap</hask> declaration takes the following form<br />
<haskell><br />
class GMapKey k where<br />
data GMap k :: * -> *<br />
...<br />
</haskell><br />
In contrast to toplevel declarations, named arguments must be used for all type parameters that are to be used as type-indexes. Moreover, the argument names must be class parameters. Each class parameter may only be used at most once per associated type, but some may be omitted and they may be in an order other than in the class head. Hence, the following contrieved example is admissible:<br />
<haskell><br />
class C a b c where<br />
data T c a :: *<br />
</haskell><br />
If kind signatures are required for argument variables, they need to be given in the class head.<br />
<br />
=== Instance declarations ===<br />
<br />
Instance declarations of data and newtype families are very similar to standard data and newtype declarations. The only two differences are that the keyword <hask>data</hask> or <hask>newtype</hask> is followed by <hask>instance</hask> and that some or all of the type arguments can be non-variable types. For example, the <hask>Either</hask> instance for <hask>GMap</hask> is<br />
<haskell><br />
data instance GMap (Either a b) v = GMapEither (GMap a v) (GMap b v)<br />
</haskell><br />
In this example, the declaration has only one variant. In general, it can be be any number.<br />
<br />
Data and newtype instance declarations are only legit when an appropriate family declaration is in scope - just like class instances require the class declaration to be visible. Moreover, each instance declaration has to conform to the kind determined by its family declaration. This implies that the number of parameters of an instance declaration matches the arity determined by the kind of the family. Although, all data families are declared with the <hask>data</hask> keyword, instances can be either <hask>data</hask> or <hask>newtype</hask>s, or a mix of both.<br />
<br />
Even if type families are defined as toplevel declarations, functions that perform different computations for different family instances still need to be defined as methods of type classes. In particular, the following is not possible:<br />
<haskell><br />
data family T a<br />
data instance T Int = A<br />
data instance T Char = B<br />
nonsence :: T a -> Int<br />
nonsence A = 1 -- WRONG: These two equations together...<br />
nonsence B = 2 -- ...will produce a type error.<br />
</haskell><br />
Given the functionality provided by GADTs (Generalised Algebraic Data Types), it might seem as if a definition, such as the above, should be feasible. However, type families are - in contrast to GADTs - are ''open''; i.e., new instances can always be added, possibly in other modules. Supporting pattern matching across different data instances would require a form of extensible case construct.<br />
<br />
==== Associated type instances ====<br />
<br />
When an associated family instance is declared within a type class instance, we drop the <hask>instance</hask> keyword in the family instance. So, the <hask>Either</hask> instance for <hask>GMap</hask> becomes:<br />
<haskell><br />
instance (GMapKey a, GMapKey b) => GMapKey (Either a b) where<br />
data GMap (Either a b) v = GMapEither (GMap a v) (GMap b v<br />
...<br />
</haskell><br />
The most important point about associated family instances is that the type indexes corresponding to class parameters must be identical to the type given in the instance head; here this is first argument of <hask>GMap</hask>, namely <hask>Either a b</hask>, which coincides with the only class parameter. Any parameters to the family constructor that do not correspond to class parameters, need to be variables in every instance; here this is the variable <hask>v</hask>.<br />
<br />
Instances for an associated family can only appear as part of instances declarations of the class in which the family was declared - just as with the equations of the methods of a class. Also in correspondence to how methods are handled, declarations of associated types can be omitted in class instances. If an associated family instance is omitted, the corresponding instance type is not inhabited; i.e., only diverging expressions, such as <hask>undefined</hask>, can assume the type.<br />
<br />
==== Class instances of type instances ====<br />
<br />
Type class instances of instances of data families can be defined as usual, and in particular data instance declarations can have <hask>deriving</hask> clauses. For example, we can write<br />
<haskell><br />
data GMap () v = GMapUnit (Maybe v)<br />
deriving Show<br />
</haskell><br />
which implcitly defines an instance of the form<br />
<haskell><br />
instance Show v => Show (GMap () v) where ...<br />
</haskell><br />
<br />
Note that class instances are always for particular ''instances'' of a data family and never for an entire family as a whole. This for essentially the same reasons that we cannot define a toplevel function that performs pattern matching on the data constructors of ''different'' instances of a single type family. It would require a form of extensible case construct.<br />
<br />
==== Overlap ====<br />
<br />
The instance declarations of a data family used in a single program may not overlap at all, independent of whether they are associated or not. In contrast to type class instances, this is not only a matter of consistency, but one of type safety.<br />
<br />
=== Import and export ===<br />
<br />
The association of data constructors with type families is more dynamic than that is the case with standard data and newtype declarations. In the standard case, the notation <hask>T(..)</hask> in an import or export list denotes the type constructor and all the data constructors introduced in its declaration. However, a family declaration never introduces any data constructors; instead, data constructors are introduced by family instances. As a result, which data constructors are associated with a type family depends on the currently visible instance declarations for that family. Consequently, an import or export item of the form <hask>T(..)</hask> denotes the family constructor and all currently visible data constructors - in the case of an export item, these may be either imported or defined in the current module. The treatment of import and export items that explicitly list data constructors, such as <hask>GMap(GMapEither)</hask>, is analogous.<br />
<br />
==== Associated families ====<br />
<br />
As expected, an import or export item of the form <hask>C(..)</hask> denotes all of the class' methods and associated types. However, when associated types are explicitly listed as subitems of a class, we need some new syntax, as uppercase identifiers as subitems are usually data constructors, not type constructors. To clarify that we denote types here, each associated type name needs to be prefixed by the keyword <hask>type</hask>. So for example, when explicitly listing the components of the <hask>GMapKey</hask> class, we write <hask>GMapKey(type GMap, empty, lookup, insert)</hask>.<br />
<br />
==== Examples ====<br />
<br />
Assuming our running <hask>GMapKey</hask> class example, let us look at some export lists and their meaning:<br />
<br />
* <hask>module GMap (GMapKey) where...</hask>: Exports just the class name.<br />
* <hask>module GMap (GMapKey(..)) where...</hask>: Exports the class, the associated type <hask>GMap</hask> and the member functions <hask>empty</hask>, <hask>lookup</hask>, and <hask>insert</hask>. None of the data constructors is exported.<br />
* <hask>module GMap (GMapKey(..), GMap(..)) where...</hask>: As before, but also exports all the data constructors <hask>GMapInt</hask>, <hask>GMapChar</hask>, <hask>GMapUnit</hask>, <hask>GMapPair</hask>, and <hask>GMapUnit</hask>.<br />
* <hask>module GMap (GMapKey(empty, lookup, insert), GMap(..)) where...</hask>: As before.<br />
* <hask>module GMap (GMapKey, empty, lookup, insert, GMap(..)) where...</hask>: As before.<br />
<br />
Finally, you can write <hask>GMapKey(type GMap)</hask> to denote both the class <hask>GMapKey</hask> as well as its associated type <hask>GMap</hask>. However, you cannot write <hask>GMapKey(type GMap(..))</hask> &mdash; i.e., sub-component specifications cannot be nested. To specify <hask>GMap</hask>'s data constructors, you have to list it separately.<br />
<br />
==== Instances ====<br />
<br />
Family instances are implicitly exported, just like class instances. However, this applies only to the heads of instances, not to the data constructors an instance defines.<br />
<br />
== Open Issues ==<br />
<br />
None.</div>Tschrijvershttps://wiki.haskell.org/index.php?title=GHC/Type_families&diff=13203GHC/Type families2007-05-24T16:39:46Z<p>Tschrijvers: </p>
<hr />
<div>[[Category:GHC|Indexed types]]<br />
== Type families in GHC ==<br />
<br />
Type families are a new addition to GHC's type extensions. They are currently an '''experimental''' feature and so their design may still change to some degree. The current implementation covers ''data families'' (including newtypes), which can either be on the toplevel or inside class declarations - the latter are also known as [http://www.cse.unsw.edu.au/~chak/papers/CKPM05.html associated data types]. <br />
<br />
'''NB:''' Please note that indexed type ''synonyms'' (and hence also associated type synonyms) are '''not''' fully implemented yet. Any attempt to use them will lead to strange error messages. For the moment, you can only use indexed <hask>data</hask> families.<br />
<br />
== What do I need to use indexed type families? ==<br />
<br />
Indexed type families are implemented in GHC's HEAD (from version 6.7), which you can obtain in binary form from the [http://www.haskell.org/ghc/dist/current/dist/ nightly snapshots] or in source form from the [http://hackage.haskell.org/trac/ghc/wiki/Building/GettingTheSources source repository]. To enable indexed type families in GHC 6.7, you need to supply the compiler option <tt>-ftype-families</tt> (or <tt>-fglasgow-exts</tt>, which implies it). NB: The option used to be called <tt>-findexed-types</tt> for a while.<br />
<br />
== An example ==<br />
<br />
As an example, consider Ralf Hinze's [http://www.informatik.uni-bonn.de/~ralf/publications.html#J4 generalised tries], a form of generic finite maps. <br />
<br />
=== The class declaration ===<br />
<br />
We define a type class whose instances are the types that we can use as keys in our generic maps:<br />
<haskell><br />
class GMapKey k where<br />
data GMap k :: * -> *<br />
empty :: GMap k v<br />
lookup :: k -> GMap k v -> Maybe v<br />
insert :: k -> v -> GMap k v -> GMap k v<br />
</haskell><br />
The interesting part is the ''associated data family'' declaration of the class. It gives a [http://www.haskell.org/ghc/docs/latest/html/users_guide/type-extensions.html#sec-kinding ''kind signature''] (here <hask>* -> *</hask>) for the associated data type <hask>GMap k</hask> - analog to how methods receive a type signature in a class declaration.<br />
<br />
What it is important to notice is that the first parameter of the associated type <hask>GMap</hask> coincides with the class parameter of <hask>GMapKey</hask>. This indicates that also in all instances of the class, the instances of the associated data type need to have their first argument match up with the instance type. In general, the type arguments of an associated type can be a subset of the class parameters (in a multi-parameter type class) and they can appear in any order, possibly in an order other than in the class head. The latter can be useful if the associated data type is partially applied in some contexts.<br />
<br />
The second important point is that as <hask>GMap k</hask> has kind <hask>* -> *</hask> and <hask>k</hask> (implicitly) has kind <hask>*</hask>, the type constructor <hask>GMap</hask> (without an argument) has kind <hask>* -> * -> *</hask>. Consequently, we see that <hask>GMap</hask> is applied to two arguments in the signatures of the methods <hask>empty</hask>, <hask>lookup</hask>, and <hask>insert</hask>.<br />
<br />
=== An Int instance ===<br />
<br />
To use Ints as keys into generic maps, we declare an instance that simply uses <hask>Data.Map</hask>, thusly:<br />
<haskell><br />
instance GMapKey Int where<br />
data GMap Int v = GMapInt (Data.Map.Map Int v)<br />
empty = GMapInt Data.Map.empty<br />
lookup k (GMapInt m) = Data.Map.lookup k m<br />
insert k v (GMapInt m) = GMapInt (Data.Map.insert k v m)<br />
</haskell><br />
The <hask>Int</hask> instance of the associated data type <hask>GMap</hask> needs to have both of its parameters, but as only the first one corresponds to a class parameter, the second needs to be a type variable (here <hask>v</hask>). As mentioned before any associated type parameter that corresponds to a class parameter must be identical to the class parameter in each instance. The right hand side of the associated data declaration is like that of any other data type.<br />
<br />
NB: At the moment, GADT syntax is not allowed for associated data types (or other indexed types). This is not a fundemental limitation, but just a shortcoming of the current implementation, which we expect to lift in the future.<br />
<br />
As an exercise, implement an instance for <hask>Char</hask> that maps back to the <hask>Int</hask> instance using the conversion functions <hask>Char.ord</hask> and <hask>Char.chr</hask>.<br />
<br />
=== A unit instance ===<br />
<br />
Generic definitions, apart from elementary types, typically cover units, products, and sums. We start here with the unit instance for <hask>GMap</hask>:<br />
<haskell><br />
instance GMapKey () where<br />
data GMap () v = GMapUnit (Maybe v)<br />
empty = GMapUnit Nothing<br />
lookup () (GMapUnit v) = v<br />
insert () v (GMapUnit _) = GMapUnit $ Just v<br />
</haskell><br />
For unit, the map is just a <hask>Maybe</hask> value.<br />
<br />
=== Product and sum instances ===<br />
<br />
Nest, let us define the instances for pairs and sums (i.e., <hask>Either</hask>):<br />
<haskell><br />
instance (GMapKey a, GMapKey b) => GMapKey (a, b) where<br />
data GMap (a, b) v = GMapPair (GMap a (GMap b v))<br />
empty = GMapPair empty<br />
lookup (a, b) (GMapPair gm) = lookup a gm >>= lookup b <br />
insert (a, b) v (GMapPair gm) = GMapPair $ case lookup a gm of<br />
Nothing -> insert a (insert b v empty) gm<br />
Just gm2 -> insert a (insert b v gm2 ) gm<br />
<br />
instance (GMapKey a, GMapKey b) => GMapKey (Either a b) where<br />
data GMap (Either a b) v = GMapEither (GMap a v) (GMap b v)<br />
empty = GMapEither empty empty<br />
lookup (Left a) (GMapEither gm1 _gm2) = lookup a gm1<br />
lookup (Right b) (GMapEither _gm1 gm2 ) = lookup b gm2<br />
insert (Left a) v (GMapEither gm1 gm2) = GMapEither (insert a v gm1) gm2<br />
insert (Right a) v (GMapEither gm1 gm2) = GMapEither gm1 (insert a v gm2)<br />
</haskell><br />
If you find this code algorithmically surprising, I'd suggest to have a look at [http://www.informatik.uni-bonn.de/~ralf/publications.html#J4 Ralf Hinze's paper]. The only novelty concerning associated types, in these two instances, is that the instances have a context <hask>(GMapKey a, GMapKey b)</hask>. Consequently, the right hand sides of the associated type declarations can use <hask>GMap</hask> recursively at the key types <hask>a</hask> and <hask>b</hask> - not unlike the method definitions use the class methods recursively at the types for which the class is given in the instance context.<br />
<br />
=== Using a generic map ===<br />
<br />
Finally, some code building and quering a generic map:<br />
<haskell><br />
myGMap :: GMap (Int, Either Char ()) String<br />
myGMap = insert (5, Left 'c') "(5, Left 'c')" $<br />
insert (4, Right ()) "(4, Right ())" $<br />
insert (5, Right ()) "This is the one!" $<br />
insert (5, Right ()) "This is the two!" $<br />
insert (6, Right ()) "(6, Right ())" $<br />
insert (5, Left 'a') "(5, Left 'a')" $<br />
empty<br />
main = putStrLn $ maybe "Couldn't find key!" id $ lookup (5, Right ()) myGMap<br />
</haskell><br />
<br />
=== Download the code ===<br />
<br />
If you want to play with this example without copying it off the wiki, just download the [http://darcs.haskell.org/testsuite/tests/ghc-regress/indexed-types/should_run/GMapAssoc.hs source code for <hask>GMap</hask>] from GHC's test suite.<br />
<br />
== Definition of the type system extension ==<br />
<br />
['''NB:''' The following material will eventually become documentation for type families in the GHC User Manual. Please help to improve it by forwarding suggestions to <tt>chak@cse.unsw.edu.au</tt>.]<br />
<br />
Data families appear in two flavours: (1) they can be defined on the toplevel or (2) they can appear inside type classes (in which case they are known as associated types). The former is the more general variant, as it lacks the requirement for the type-indexes to coincide with the class parameters. However, the later can lead to more clearly structured code and compiler warnings if some type instances were - possibly accidentally - omitted. In the following, we always discuss the general toplevel form first and then cover the additional constraints placed on associated types.<br />
<br />
=== Family declarations ===<br />
<br />
Indexed data families are introduced by a signature, such as <br />
<haskell><br />
data family GMap k :: * -> *<br />
</haskell><br />
The special <hask>family</hask> distinguishes family from standard data declarations. The result kind annotation is optional and, as usual, defaults to <hask>*</hask> if omitted. An example is<br />
<haskell><br />
data family Array e<br />
</haskell><br />
Named arguments can also be given explicit kind signatures if needed. Just as with [http://www.haskell.org/ghc/docs/latest/html/users_guide/gadt.html GADT declarations] named arguments are entirely optional, so that we can declare <hask>Array</hask> alternatively with<br />
<haskell><br />
data family Array :: * -> *<br />
</haskell><br />
<br />
==== Associated family declarations ====<br />
<br />
When a data family is declared as part of a type class, we drop the <hask>family</hask> special. The <hask>GMap</hask> declaration takes the following form<br />
<haskell><br />
class GMapKey k where<br />
data GMap k :: * -> *<br />
...<br />
</haskell><br />
In contrast to toplevel declarations, named arguments must be used for all type parameters that are to be used as type-indexes. Moreover, the argument names must be class parameters. Each class parameter may only be used at most once per associated type, but some may be omitted and they may be in an order other than in the class head. Hence, the following contrieved example is admissible:<br />
<haskell><br />
class C a b c where<br />
data T c a :: *<br />
</haskell><br />
If kind signatures are required for argument variables, they need to be given in the class head.<br />
<br />
=== Instance declarations ===<br />
<br />
Instance declarations of data and newtype families are very similar to standard data and newtype declarations. The only two differences are that the keyword <hask>data</hask> or <hask>newtype</hask> is followed by <hask>instance</hask> and that some or all of the type arguments can be non-variable types. For example, the <hask>Either</hask> instance for <hask>GMap</hask> is<br />
<haskell><br />
data instance GMap (Either a b) v = GMapEither (GMap a v) (GMap b v)<br />
</haskell><br />
In this example, the declaration has only one variant. In general, it can be be any number.<br />
<br />
Data and newtype instance declarations are only legit when an appropriate family declaration is in scope - just like class instances require the class declaration to be visible. Moreover, each instance declaration has to conform to the kind determined by its family declaration. This implies that the number of parameters of an instance declaration matches the arity determined by the kind of the family. Although, all data families are declared with the <hask>data</hask> keyword, instances can be either <hask>data</hask> or <hask>newtype</hask>s, or a mix of both.<br />
<br />
Even if type families are defined as toplevel declarations, functions that perform different computations for different family instances still need to be defined as methods of type classes. In particular, the following is not possible:<br />
<haskell><br />
data family T a<br />
data instance T Int = A<br />
data instance T Char = B<br />
nonsence :: T a -> Int<br />
nonsence A = 1 -- WRONG: These two equations together...<br />
nonsence B = 2 -- ...will produce a type error.<br />
</haskell><br />
Given the functionality provided by GADTs (Generalised Algebraic Data Types), it might seem as if a definition, such as the above, should be feasible. However, type families are - in contrast to GADTs - are ''open''; i.e., new instances can always be added, possibly in other modules. Supporting pattern matching across different data instances would require a form of extensible case construct.<br />
<br />
==== Associated type instances ====<br />
<br />
When an associated family instance is declared within a type class instance, we drop the <hask>instance</hask> keyword in the family instance. So, the <hask>Either</hask> instance for <hask>GMap</hask> becomes:<br />
<haskell><br />
instance (GMapKey a, GMapKey b) => GMapKey (Either a b) where<br />
data GMap (Either a b) v = GMapEither (GMap a v) (GMap b v<br />
...<br />
</haskell><br />
The most important point about associated family instances is that the type indexes corresponding to class parameters must be identical to the type given in the instance head; here this is first argument of <hask>GMap</hask>, namely <hask>Either a b</hask>, which coincides with the only class parameter. Any parameters to the family constructor that do not correspond to class parameters, need to be variables in every instance; here this is the variable <hask>v</hask>.<br />
<br />
Instances for an associated family can only appear as part of instances declarations of the class in which the family was declared - just as with the equations of the methods of a class. Also in correspondence to how methods are handled, declarations of associated types can be omitted in class instances. If an associated family instance is omitted, the corresponding instance type is not inhabited; i.e., only diverging expressions, such as <hask>undefined</hask>, can assume the type.<br />
<br />
==== Class instances of type instances ====<br />
<br />
Type class instances of instances of data families can be defined as usual, and in particular data instance declarations can have <hask>deriving</hask> clauses. For example, we can write<br />
<haskell><br />
data GMap () v = GMapUnit (Maybe v)<br />
deriving Show<br />
</haskell><br />
which implcitly defines an instance of the form<br />
<haskell><br />
instance Show v => Show (GMap () v) where ...<br />
</haskell><br />
<br />
Note that class instances are always for particular ''instances'' of a data family and never for an entire family as a whole. This for essentially the same reasons that we cannot define a toplevel function that performs pattern matching on the data constructors of ''different'' instances of a single type family. It would require a form of extensible case construct.<br />
<br />
==== Overlap ====<br />
<br />
The instance declarations of a data family used in a single program may not overlap at all, independent of whether they are associated or not. In contrast to type class instances, this is not only a matter of consistency, but one of type safety.<br />
<br />
=== Import and export ===<br />
<br />
The association of data constructors with type families is more dynamic than that is the case with standard data and newtype declarations. In the standard case, the notation <hask>T(..)</hask> in an import or export list denotes the type constructor and all the data constructors introduced in its declaration. However, a family declaration never introduces any data constructors; instead, data constructors are introduced by family instances. As a result, which data constructors are associated with a type family depends on the currently visible instance declarations for that family. Consequently, an import or export item of the form <hask>T(..)</hask> denotes the family constructor and all currently visible data constructors - in the case of an export item, these may be either imported or defined in the current module. The treatment of import and export items that explicitly list data constructors, such as <hask>GMap(GMapEither)</hask>, is analogous.<br />
<br />
==== Associated families ====<br />
<br />
As expected, an import or export item of the form <hask>C(..)</hask> denotes all of the class' methods and associated types. However, when associated types are explicitly listed as subitems of a class, we need some new syntax, as uppercase identifiers as subitems are usually data constructors, not type constructors. To clarify that we denote types here, each associated type name needs to be prefixed by the keyword <hask>type</hask>. So for example, when explicitly listing the components of the <hask>GMapKey</hask> class, we write <hask>GMapKey(type GMap, empty, lookup, insert)</hask>.<br />
<br />
==== Examples ====<br />
<br />
Assuming our running <hask>GMapKey</hask> class example, let us look at some export lists and their meaning:<br />
<br />
* <hask>module GMap (GMapKey) where...</hask>: Exports just the class name.<br />
* <hask>module GMap (GMapKey(..)) where...</hask>: Exports the class, the associated type <hask>GMap</hask> and the member functions <hask>empty</hask>, <hask>lookup</hask>, and <hask>insert</hask>. None of the data constructors is exported.<br />
* <hask>module GMap (GMapKey(..), GMap(..)) where...</hask>: As before, but also exports all the data constructors <hask>GMapInt</hask>, <hask>GMapChar</hask>, <hask>GMapUnit</hask>, <hask>GMapPair</hask>, and <hask>GMapUnit</hask>.<br />
* <hask>module GMap (GMapKey(empty, lookup, insert), GMap(..)) where...</hask>: As before.<br />
* <hask>module GMap (GMapKey, empty, lookup, insert, GMap(..)) where...</hask>: As before.<br />
<br />
Finally, you can write <hask>GMapKey(type GMap)</hask> to denote both the class <hask>GMapKey</hask> as well as its associated type <hask>GMap</hask>. However, you cannot write <hask>GMapKey(type GMap(..))</hask> &mdash; i.e., sub-component specifications cannot be nested. To specify <hask>GMap</hask>'s data constructors, you have to list it separately.<br />
<br />
==== Instances ====<br />
<br />
Family instances are implicitly exported, just like class instances. However, this applies only to the heads of instances, not to the data constructors an instance defines.<br />
<br />
== Open Issues ==<br />
<br />
None.</div>Tschrijvers