https://wiki.haskell.org/api.php?action=feedcontributions&user=Simonpj&feedformat=atomHaskellWiki - User contributions [en]2020-11-28T14:45:26ZUser contributionsMediaWiki 1.27.4https://wiki.haskell.org/index.php?title=Performance&diff=61142Performance2016-09-29T07:33:54Z<p>Simonpj: /* More information */</p>
<hr />
<div>{{Performance infobox}}<br />
Welcome to the '''Haskell Performance Resource''', the collected wisdom on how to make your Haskell programs go faster. <br />
<br />
== Introduction ==<br />
<br />
One question that often comes up is along the general lines of "Can I write this program in Haskell so that it performs as well as, or better than, the same program written in some other language?"<br />
<br />
This is a difficult question to answer in general because Haskell is a language, not an implementation. Performance can only be measured relative to a specific language implementation.<br />
<br />
Moreover, it's often not clear if two programs which supposedly have the same functionality really do the same thing. Different languages sometimes require very different ways of expressing the same intent. Certain types of bug are rare in typical Haskell programs that are more common in other languages and vice versa, due to strong typing, automatic memory management and lazy evaluation.<br />
<br />
Nonetheless, it is usually possible to write a Haskell program that performs as well as, or better than, the same program written in any other language. The main caveat is that you may have to modify your code significantly in order to improve its performance. Compilers such as GHC are good at eliminating layers of abstraction, but they aren't perfect, and often need some help. <br />
<br />
There are many non-invasive techniques: compiler options, for example. Then there are techniques that require adding some small amounts of performance cruft to your program: strictness annotations, for example. If you still don't get the best performance, though, it might be necessary to resort to larger refactorings.<br />
<br />
Sometimes the code tweaks required to get the best performance are non-portable, perhaps because they require language extensions that aren't implemented in all compilers (e.g. unboxing), or because they require using platform-specific features or libraries. This might not be acceptable in your setting.<br />
<br />
If the worst comes to the worst, you can always write your critical code in C and use the FFI to call it. Beware of the boundaries though - marshaling data across the FFI can be expensive, and multi-language memory management can be complex and error-prone. It's usually better to stick to Haskell if possible.<br />
<br />
== Basic techniques ==<br />
<br />
The key tool to use in making your Haskell program run faster is ''profiling''. Profiling is provided by [[GHC]] and [[nhc98]]. There is ''no substitute'' for finding where your program's time/space is ''really'' going, as opposed to where you imagine it is going.<br />
<br />
Another point to bear in mind: By far the best way to improve a program's performance ''dramatically'' is to use better algorithms. Once profiling has thrown the spotlight on the guilty time-consumer(s), it may be better to re-think your program than to try all the tweaks listed below.<br />
<br />
Another extremely efficient way to make your program snappy is to use library code that has been Seriously Tuned By Someone Else. You ''might'' be able to write a better sorting function than the one in <tt>Data.List</tt>, but it will take you much longer than typing <tt>import Data.List</tt>.<br />
<br />
We have chosen to organise the rest of this resource first by Haskell construct (data types, pattern matching, integers), and then within each category to describe techniques that apply across implementations, and also techniques that are specific to a certain Haskell implementation (e.g. GHC). There are some implementation-specific techniques that apply in general - those are linked from the [[Haskell Performance Resource#General_Implementation-Specific_Techniques | General Implementation-Specific Techniques]] section below.<br />
<br />
== Haskell constructs ==<br />
<br />
* [[/Data Types/]]<br />
* [[/Functions/]]<br />
* [[/Overloading/]]<br />
* [[/FFI/]]<br />
* [[/Arrays/]]<br />
* [[/Strings/]]<br />
* [[/Integers/]]<br />
* [[/IO | I/O ]]<br />
* [[/Floating Point/]]<br />
* [[/Concurrency/]]<br />
* [[/Modules/]]<br />
* [[/Monads/]]<br />
<br />
== General techniques ==<br />
<br />
The most important thing for a beginner to keep in mind is that Haskell programs are evaluated using [[lazy evaluation]], which has many advantages, but also drawbacks when it comes to performance. The rule of thumb is that if you really want to have explicit control over the evaluation, then you should try to avoid it.<br />
<br />
* [[/Strictness/]]<br />
* [[/Laziness/]]<br />
* [[/Space | Avoiding space leaks]]<br />
* [[/Accumulating parameter|Accumulating parameters]]<br />
* [[Stack_overflow|Avoiding stack overflow]]<br />
<br />
== Benchmarking libraries ==<br />
<br />
The [[Criterion]] library is used often to generate detailed benchmark results.<br />
<br />
* [http://www.serpentine.com/blog/2009/09/29/criterion-a-new-benchmarking-library-for-haskell/ Introductory blog post]<br />
* [http://www.stackbuilders.com/news/obverse-versus-reverse-benchmarking-in-haskell-with-criterion Simple example of using Criterion]<br />
<br />
== Compiler specific techniques ==<br />
<br />
* [[/GHC/]]<br />
* [[/NHC98| nhc98]]<br />
* [[/Hugs/]]<br />
* [[/Yhc/]]<br />
* [[/JHC/]]<br />
<br />
== More information ==<br />
<br />
* [http://www.well-typed.com/blog/2016/09/sharing-conduit/ Sharing, Memory Leaks, and Conduit and friends], 2016. Edsko's war stories. Sharing conduit values leads to memory leaks. Make sure to disable the full laziness optimization in the module with your top-level calls to <tt>runConduit</tt> or <tt>($$)</tt>. Similar considerations apply to other streaming libraries and indeed any Haskell code that uses lazy data structures to drive computation. <br />
<br />
* [https://donsbot.wordpress.com/2008/06/04/haskell-as-fast-as-c-working-at-a-high-altitude-for-low-level-performance/ Haskell as fast as C: working at a high altitude for low level performance]<br />
<br />
* [http://www.randomhacks.net/2007/01/22/high-performance-haskell/ High-Performance Haskell] ([http://www.slideshare.net/tibbe/highperformance-haskell Slide deck])<br />
<br />
* [http://lambda.jstolarek.com/2013/04/haskell-as-fast-as-c-a-case-study/ Haskell as fast as C: A case study]<br />
<br />
* [https://www.youtube.com/watch?v=McFNkLPTOSY&feature=youtu.be Dan Doel - Introduction to Low Level Haskell Optimization]; a video of Dan Doel's talk at the Boston Haskell Meetup, Sept 17, 2014 ([http://hub.darcs.net/dolio/optimization-talk-demo/browse/slides/slides.md slides]).<br />
<br />
* Don Stewart's [http://stackoverflow.com/questions/3276240/tools-for-analyzing-performance-of-a-haskell-program/3276557#3276557 Haskell performance overview] on StackOverflow (2013)<br />
<br />
* There are plenty of good examples of Haskell code written for performance in the [http://benchmarksgame.alioth.debian.org/ The Computer Language Benchmarks Game]<br />
<br />
* And many alternatives, with discussion, on this wiki: [[Benchmarks Game]] and on the [http://web.archive.org/web/20060209215702/http://haskell.org/hawiki/ShootoutEntry old Haskell wiki] (in the Web Archive)<br />
<br />
* There are ~100 [http://blog.johantibell.com/2010/09/slides-from-my-high-performance-haskell.html slides on High-Performance Haskell] from the 2010 CUFP tutorial on that topic.<br />
<br />
== Specific comparisons of data structures ==<br />
<br />
=== Ropes ===<br />
<br />
For modifying very long strings, a [https://en.wikipedia.org/wiki/Rope_(data_structure) rope data structure] is very efficient. The [https://hackage.haskell.org/package/rope rope] package provides these.<br />
<br />
=== Data.Sequence vs. lists ===<br />
<br />
Data.Sequence has complexity O(log(min(i,n-i))) for access, insertion and update to position i of a sequence of length n.<br />
<br />
List has complexity O(i).<br />
<br />
List is a non-trivial constant-factor faster for operations at the head (cons and head), making it a more efficient choice for stack-like and stream-like access patterns. Data.Sequence is faster for every other access pattern, such as queue and random access.<br />
<br />
See the following program for proof:<br />
<haskell><br />
import Data.Sequence<br />
<br />
insert_million 0 sequence = sequence<br />
insert_million n sequence = insert_million (n - 1)(sequence |> n)<br />
<br />
main = print (Data.Sequence.length (insert_million 1000000 empty))<br />
</haskell><br />
<pre><br />
$ ghc -O2 --make InsertMillionElements.hs && time ./InsertMillionElements +RTS -K100M<br />
1000000<br />
real 0m7.238s<br />
user 0m6.804s<br />
sys 0m0.228s<br />
</pre><br />
<haskell><br />
insert_million 0 list = reverse list<br />
insert_million n list = insert_million (n -1) (n:list)<br />
<br />
main = print (length (insert_million 1000000 []))<br />
</haskell><br />
<pre><br />
$ ghc -O2 --make InsertMillionElements.hs && time ./InsertMillionElementsList +RTS -K100M<br />
1000000<br />
real 0m0.588s<br />
user 0m0.528s<br />
sys 0m0.052s<br />
</pre><br />
Lists are substantially faster on this micro-benchmark.<br />
<br />
A sequence uses between 5/6 and 4/3 times as much space as the equivalent list (assuming an overhead of one word per node, as in GHC).<br />
If only deque operations are used, the space usage will be near the lower end of the range, because all internal nodes will be ternary.<br />
Heavy use of split and append will result in sequences using approximately the same space as lists.<br />
In detail:<br />
* a list of length ''n'' consists of ''n'' cons nodes, each occupying 3 words.<br />
* a sequence of length ''n'' has approximately ''n''/(''k''-1) nodes, where ''k'' is the average arity of the internal nodes (each 2 or 3). There is a pointer, a size and overhead for each node, plus a pointer for each element, i.e. ''n''(3/(''k''-1) + 1) words.<br />
<br />
== Additional Tips ==<br />
<br />
* Use strict returns ( return $! ...) unless you absolutely need them lazy.<br />
* Profile, profile, profile - understand who is allocated the memory on your heap (+RTS -hc) and how it's being used (+RTS -hb).<br />
* Use +RTS -p to understand who's doing all the allocations and where your time is being spent.<br />
* Approach profiling like a science experiment - make one change, observe if anything is different, rollback and make another change - observe the change. Keep notes!<br />
* Use [[ThreadScope]] to visualize GHC eventlog traces.<br />
<br />
[[Category:Idioms]]<br />
[[Category:Language]]<br />
[[Category:Performance|*]]</div>Simonpjhttps://wiki.haskell.org/index.php?title=Hackage_trustees&diff=59304Hackage trustees2015-02-12T12:11:16Z<p>Simonpj: /* Trustee powers */</p>
<hr />
<div>The role of '''Hackage trustees''' is to help to curate the whole [[Hackage]] package collection. Trustees have a limited ability to edit package information, for the entire package database (as opposed to package maintainers who have full control over individual packages). Trustees can edit .cabal files, edit other package metadata and upload documentation but they cannot upload new package versions.<br />
<br />
== Purpose ==<br />
<br />
Individual authors and maintainers look after individual packages. In Linux distributions and the like, there are people who look after the health of the collection of packages as a whole. They curate the whole collection to keep things healthy. Hackage trustees are intended to fulfil a similar role, but upstream with hackage itself rather than in distros downstream.<br />
<br />
The goal is to improve the quality of the package collection. One of the key ways the can do this is by editing package metadata, particularly to constrain dependencies when packages are found to be incompatible.<br />
<br />
As features like package tagging are improved, trustees may be given additional abilities, such as curating the quality of tags used for categorising and searching for packages (e.g. merging tags that are deemed to be aliases).<br />
<br />
== Current trustees ==<br />
<br />
The server has a special user group called "trustees", so the current list of trustees is always available at https://hackage.haskell.org/packages/trustees/<br />
<br />
The whole trustee system, and metadata editing feature is still somewhat in its infancy. The initial trustees were appointed by the hackage admins based on their previous volunteer work in this area. There is currently no formal process for becoming a trustee.<br />
<br />
== Trustee powers ==<br />
<br />
Trustees have some of the same powers as package maintainers, but for all packages on hackage. In particular they can <br />
<br />
* upload documentation, <br />
* edit package categories/tags, <br />
* edit the .cabal files, in the same way that maintainers can. <br />
<br />
This last aspect is the most useful for curating hackage and improving quality, but it is also the most controversial.<br />
<br />
Trustees '''cannot''' upload new versions of packages, only maintainers can do this.<br />
<br />
There has not yet been very extensive use of these powers as a full discussion with the Haskell package developer community needs to be had first, so that a policy that strikes the proper balance can be agreed, and so that package maintainers are properly informed. Up until now, trustees have mostly been curating some of the more core packages, or with the cooperation of the maintainers.<br />
<br />
The trustees are currently preparing a proposal to discuss with package authors/maintainers on the Haskell libraries mailing list.<br />
<br />
== Trustee resources ==<br />
<br />
* Issue tracker for [https://github.com/haskell-infra/hackage-trustees/ coordinating Hackage maintenance and trustee operations]</div>Simonpjhttps://wiki.haskell.org/index.php?title=Library_submissions&diff=59300Library submissions2015-02-11T16:25:38Z<p>Simonpj: </p>
<hr />
<div>This page describes the process for maintaining the <br />
'''Core libraries'''. The core libraries form a subset of the packages in the<br />
Haskell Platform that has submitted to the management process described herein. <br />
<br />
These packages typically define basic APIs that are expected to be<br />
available in any Haskell implementation, packages that are being maintained for backwards compatibility, or in some cases, which are just needed as glue to hold the rest of the platform together.<br />
<br />
They are listed under "The Core Libraries" below.<br />
<br />
Many core libraries are managed by their own authors/maintainers.<br />
<br />
The [http://www.haskell.org/haskellwiki/Core_Libraries_Committee Core Libraries Committee], however, acts as a collective maintainer for those core libraries that do not have a specific maintainer.<br />
<br />
Non-core libraries can be maintained by their own authors/maintainers (named in their .cabal file), using whatever policies those maintainers see fit. [Note: arguably the policies below might usefully be applied to all libraries embodied in the Haskell Platform, but that is a question for the HP team.]<br />
<br />
However, if you maintain a package in the Haskell Platform, it would at least be a good idea to follow the libraries mailing list.<br />
<br />
= General principles =<br />
<br />
* Each core package has a named maintainer, or small group of maintainers, who have commit access to the package. <br />
<br />
* Third parties are encouraged to make proposals for changes, both to the library API and its implementation, by sending the proposal to the maintainer (CC'ing the libraries mailing list).<br />
<br />
* The maintainer is trusted to decide what changes to make to the package, and when. They are strongly encouraged to follow the guidance below, but the general principle is: the community offers opinions, but the maintainers decide.<br />
<br />
= Guidance for proposers =<br />
<br />
A "proposal" can be anything from a one-sentence suggestion to a fully-implemented, tested, and documented patch.<br />
However, the more substantial the proposal the more attention you can expect. The process is this:<br />
<br />
* Send your proposal by email to the maintainer, with a copy to the libraries@haskell.org mailing list (which you need to [http://www.haskell.org/mailman/listinfo/libraries subscribe] to before posting).<br />
<br />
* Set a deadline for discussion (no less than two weeks), and act as chair/moderator for the discussion. <br />
<br />
* At the end of the discussion period, summarise your understanding of the consensus (or lack thereof), including a link to the thread in the mailing list archives, and send the summary to the maintainer for decision. The deadline gives you a moment to summarise the debate and hand over to the maintainer. It isn't a deadline for the maintainer to decide; for example he or she may seek more discussion first. <br />
<br />
* If the decision is positive, [http://hackage.haskell.org/trac/ghc/newticket create a ticket] on the GHC trac. The description of the ticket can summarise the proposal and link to the mail thread. Further discussion and implementation patches can be attached to the ticket, and the ticket helps the maintainer to keep track of what is on the go. (Obviously if the maintainer prefers some other mechanism, follow his or her guidance.)<br />
<br />
* For non-trivial changes the maintainer may ask for a patch. You may create the patch up front, and make it part of your proposal; or you may want to have some discussion about the design first, and only then roll up your sleeves to do the implementation; and for bigger jobs you may want to wait until the maintainer agrees in principle with the change.<br />
<br />
Here are desirable properties for a proposal and its implementation. The more of these properties your proposal or patch has, the more likely it is that the maintainer will adopt your idea. After all, to adopt it the maintainter will have to do whatever tasks you didn't do.<br />
<br />
* '''Description'''. A good proposal says clearly ''what'' you propose, ''why'' it is a good idea, and what its consequences would be.<br />
* '''Patch'''. Use <tt>darcs record</tt> or <tt>git commit</tt> (depending on what sort of repo the library lives in) to create it. Save the patch to a file, using <tt>darcs send --output</tt> or <tt>git format-patch</tt>. Make your changes against a copy of the master branch of the relevant library, and make sure it compiles.<br />
* '''Portability'''. Good code is portable. In particular, try to ensure the code runs in Hugs and GHC, and on Windows and Linux.<br />
* '''Style'''. Good code follows the conventions in the library you are modifying.<br />
* '''Documentation'''. Good code includes valid [http://haskell.org/haddock Haddock] documentation.<br />
* '''Tests'''. Good patches have suitable tests for the library's testsuite.<br />
<br />
= Guidance for maintainers =<br />
<br />
The principle is that we '''trust the maintainer''' to behave sensibly. The guidelines below are just that: guidelines, not rules. Still, the core libraries are used by many, many people, so maintainers should make every effort not to mess them up by accident. <br />
<br />
* '''API changes should be discussed''' on the libraries mailing list prior to making the change, even if the maintainer is the proposer. The maintainer still has ultimate say in what changes are made, but the community should have the opportunity to comment on changes. However, unanimity (or even a majority) is not required.<br />
<br />
* '''Every API change should be described precisely in the commit log.''' The commit logs should be sent to a public mailing list, or otherwise made easily available (e.g. via github), so that the community can keep an eye on changes and comment.<br />
<br />
* '''Backwards compatibility''' is important to many users. API changes are expected to retain backwards compatibility wherever possible. However, from time to time we may decide to have major revisions which are explicitly not backwards compatible; in these cases we may try to make the previous version of the package available concurrently, as in the base-3/base-4 switchover.<br />
<br />
* You don't need to consult the community for '''purely internal changes'''; i.e. changes that do not affect the library's clients.<br />
<br />
* Changes that simply '''widen the API by adding new functions''' are a bit of a grey area. It's better to consult the community, because there may be useful feedback about (say) the order of arguments, or the name of the function, or whatnot. On the other hand few clients will actually break if you add a new function to the API. Use your judgment.<br />
<br />
Libraries maintained by the GHC team are subject to the GHC validation policy - patches will be tested for validation before committing ([http://hackage.haskell.org/trac/ghc/wiki/TestingPatches TestingPatches]). Those packages not maintained by the GHC team will probably have a GHC lagging mirror repository that is subject to validation.<br />
<br />
= Responsiveness =<br />
<br />
* Third parties submitting proposals to the maintainer of a library can expect a timely and thoughtful response. <br />
* The more effort the proposer invests (for example, by constructing a patch rather than making an off-the-cuff suggestion) the more consideration s/he can reasonably expect.<br />
* Proposals that have widespread support, and are accompanied by patches (preferably with tests and documentation), should normally be accepted by the maintainer. <br />
* It is up to the maintainer to decide what "widespread" means; in particular, it does not always mean "a majority of those who responded". The majority-responder story is vulnerable to selection bias; e.g. 7 people (out of a client base of hundreds) say "add this function" but the maintainer thinks it will make the interface incrementally more complicated without sufficient benefit.<br />
* Where there is significant work involved in implementing a proposal, it is reasonable for a maintainer to ask for a patch. The principle is that maintainers are not obliged to do the work of implementing a proposal, even if it does enjoy wide support. For more substantial changes, it makes sense to develop the implementation in dialogue with the maintainer.<br />
<br />
= The Core Libraries =<br />
<br />
The following packages constitute the core libraries:<br />
<br />
{| border="1"<br />
! Package !! Maintainer<br />
|-<br />
| [http://hackage.haskell.org/package/array array] || Core Libraries Committee<br />
|-<br />
| [http://hackage.haskell.org/package/base base] || Core Libraries Committee<br />
|-<br />
| [http://hackage.haskell.org/package/containers containers] || Johan Tibell and Milan Straka<br />
|-<br />
| [http://hackage.haskell.org/package/deepseq deepseq] || Core Libraries Committee<br />
|-<br />
| [http://hackage.haskell.org/package/directory directory] || Core Libraries Committee <br />
|-<br />
| [http://hackage.haskell.org/package/filepath filepath] || Neil Mitchell <br />
|-<br />
| [http://hackage.haskell.org/package/ghc-prim ghc-prim] || GHC HQ<br />
|-<br />
| [http://hackage.haskell.org/package/hpc hpc] || GHC HQ <br />
|-<br />
| [http://hackage.haskell.org/package/mtl mtl] || Edward Kmett<br />
|-<br />
| [http://hackage.haskell.org/package/parallel parallel] || Simon Marlow<br />
|-<br />
| [http://hackage.haskell.org/package/pretty pretty] || David Terei<br />
|-<br />
| [http://hackage.haskell.org/package/primitive primitive] || Core Libraries Committee<br />
|-<br />
| [http://hackage.haskell.org/package/process process] || Core Libraries Committee <br />
|-<br />
| [http://hackage.haskell.org/package/random random] || Core Libraries Committee <br />
|-<br />
| [http://hackage.haskell.org/package/template-haskell template-haskell] || Core Libraries Committee<br />
|-<br />
| [http://hackage.haskell.org/package/time time] || Ashley Yakeley<br />
|-<br />
| [http://hackage.haskell.org/package/unix unix] || Core Libraries Committee<br />
|-<br />
| [http://hackage.haskell.org/package/vector vector] || Core Libraries Committee<br />
|-<br />
| [http://hackage.haskell.org/package/Win32 Win32] || Core Libraries Committee<br />
|-<br />
| [http://hackage.haskell.org/package/xhtml xhtml] || Chris Dornan<br />
|}<br />
<br />
The maintainer "GHC HQ" means Simon Marlow, Simon Peyton Jones, and Ian Lynagh. Daniel Fischer has taken responsibility for numeric stuff. Email ghc-devs@haskell.org<br />
<br />
The [http://www.haskell.org/haskellwiki/Core_Libraries_Committee Core Libraries Committee] was formed to provide a maintainer of many of the packages previously managed by GHC HQ and can be reached by emailing core-libraries-committee@haskell.org or publicly through libraries@haskell.org.<br />
<br />
The following packages match the appropriate language standard, and as such cannot change independently. The code is maintained by the GHC team.<br />
<br />
{| border="1"<br />
|-<br />
| [http://hackage.haskell.org/package/haskell2010 haskell2010] || GHC HQ<br />
|-<br />
| [http://hackage.haskell.org/package/haskell98 haskell98] || GHC HQ<br />
|}<br />
<br />
These packages are maintained only for backward compatibility, and are not expected to undergo API changes in the future. <br />
<br />
{| border="1"<br />
|-<br />
| [http://hackage.haskell.org/package/old-locale old-locale] || Core Libraries Committee <br />
|-<br />
| [http://hackage.haskell.org/package/old-time old-time] || Core Libraries Committee <br />
|}<br />
<br />
= See also =<br />
<br />
* [http://hackage.haskell.org/trac/ghc/wiki/WorkingConventions GHC Working Conventions], including guidelines for submitting patches via darcs.<br />
* [http://haskell.org/haskellwiki/Category:Style Notes on programming style]<br />
<br />
[[Category:Community]]<br />
[[Category:Proposals| ]]</div>Simonpjhttps://wiki.haskell.org/index.php?title=Template_Haskell&diff=59049Template Haskell2014-10-30T08:33:34Z<p>Simonpj: /* Other useful resources */</p>
<hr />
<div>'''[http://hackage.haskell.org/package/template-haskell Template Haskell]''' is a [[GHC]] extension to Haskell that adds compile-time metaprogramming facilities. The original design can be found here: http://research.microsoft.com/en-us/um/people/simonpj/papers/meta-haskell/. It is [http://www.haskell.org/ghc/docs/latest/html/users_guide/template-haskell.html included] in GHC since version 6. <br />
<br />
This page hopes to be a more central and organized repository of TH related things.<br />
<br />
<br />
=What is Template Haskell?=<br />
<br />
Template Haskell is an extension to Haskell 98 that allows you to do type-safe compile-time meta-programming, with Haskell both as the manipulating language and the language being manipulated. <br />
<br />
Intuitively Template Haskell provides new language features that allow us to convert back and forth between concrete syntax, i.e. what you would type when you write normal Haskell code, and abstract syntax trees. These abstract syntax trees are represented using Haskell datatypes and, at compile time, they can be manipulated by Haskell code. This allows you to reify (convert from concrete syntax to an abstract syntax tree) some code, transform it and splice it back in (convert back again), or even to produce completely new code and splice that in, while the compiler is compiling your module. <br />
<br />
For email about Template Haskell, use the [http://www.haskell.org/mailman/listinfo/glasgow-haskell-users GHC users mailing list]. It's worth joining if you start to use TH.<br />
<br />
<br />
= Template Haskell specification =<br />
<br />
Template Haskell is only documented rather informally at the moment. Here are the main resources:<br />
<br />
* [http://www.haskell.org/ghc/docs/latest/html/users_guide/template-haskell.html The user manual section on Template Haskell]<br />
* [http://www.haskell.org/ghc/docs/latest/html/users_guide/template-haskell.html#th-quasiquotation The user manual section on quasi-quotation], which is closely related to Template Haskell.<br />
* [http://research.microsoft.com/~simonpj/papers/meta-haskell/ The original Template Haskell paper]<br />
* [http://research.microsoft.com/en-us/um/people/simonpj/tmp/notes2.ps Notes on Template Haskell version 2], which describes changes since the original paper. Section 8 describes the difficulty with pattern splices, which are therefore not implemented.<br />
* [http://hackage.haskell.org/package/template-haskell The Template Haskell API]<br />
<br />
= Template Haskell tutorials and papers =<br />
<br />
* Bulat's tutorials:<br />
*# [http://web.archive.org/web/20100703060856/http://www.haskell.org/bz/thdoc.htm Wayback Machine], [http://docs.google.com/uc?id=0B4BgTwf_ng_TM2MxZjJjZjctMTQ0OS00YzcwLWE5N2QtMDI0YzE4NGUwZDM3 Google Docs]<br />
*# [http://web.archive.org/web/20100703060841/http://www.haskell.org/bz/th3.htm Wayback Machine], [http://docs.google.com/uc?id=0B4BgTwf_ng_TOGJkZjM4ZTUtNGY5My00ZThhLTllNDQtYzJjMWJiMzJhZjNj Google Docs]<br />
<br />
: One reader said "These docs are *brilliant* ! Exactly what I need to get an understanding of TH."<br />
<br />
<small>(Note: These documents are from [http://www.archive.org the Wayback machine] because the originals disappeared. They're public documents on Google docs, which shouldn't require logging in. However, if you're asked to sign in to view them, you're running into a known Google bug. You can fix it by browsing to [http://www.google.com Google], presumably gaining a cookie in the process.)</small><br />
<br />
<!--<br />
* Mark Snyder's Template Haskell chapter on the Software Generation and Configuration Report<br />
** http://nix.cs.uu.nl/dist/courses/sgc-report-unstable-latest/manual/chunk-chapter/templatehaskell.html<br />
--><br />
* A very short tutorial to understand the basics in 10 Minutes.<br />
** http://www.hyperedsoftware.com/blog/entries/first-stab-th.html<br />
<br />
* GHC Template Haskell documentation<br />
** http://www.haskell.org/ghc/docs/latest/html/users_guide/template-haskell.html<br />
<br />
* Papers about Template Haskell<br />
<br />
** Template metaprogramming for Haskell, by Tim Sheard and Simon Peyton Jones, Oct 2002. [[http://www.haskell.org/wikiupload/c/ca/Meta-haskell.ps ps]]<br />
** Template Haskell: A Report From The Field, by Ian Lynagh, May 2003. [[http://www.haskell.org/wikiupload/2/24/Template_Haskell-A_Report_From_The_Field.ps ps]]<br />
** Unrolling and Simplifying Expressions with Template Haskell, by Ian Lynagh, December 2002. [[http://www.haskell.org/wikiupload/e/ed/Template-Haskell-Utils.ps ps]]<br />
** Automatic skeletons in Template Haskell, by Kevin Hammond, Jost Berthold and Rita Loogen, June 2003. [[http://www.haskell.org/wikiupload/6/69/AutoSkelPPL03.pdf pdf]]<br />
** Optimising Embedded DSLs using Template Haskell, by Sean Seefried, Manuel Chakravarty, Gabriele Keller, March 2004. [[http://www.haskell.org/wikiupload/b/b5/Seefried04th-pan.pdf pdf]]<br />
** Typing Template Haskell: Soft Types, by Ian Lynagh, August 2004. [[http://www.haskell.org/wikiupload/7/72/Typing_Template_Haskell_Soft_Types.ps ps]]<br />
<br />
= Other useful resources =<br />
<br />
* (2011) [https://github.com/leonidas/codeblog/blob/master/2011/2011-12-27-template-haskell.md Basic Tutorial of Template Haskell] <br />
<br />
* (2011) Greg Weber's [http://www.yesodweb.com/blog/2011/10/code-generation-conversation blog post on Template Haskell and quasi-quoting] in the context of Yesod.<br />
<br />
* (2012) Mike Ledger's [http://quasimal.com/posts/2012-05-25-quasitext-and-quasiquoting.html tutorial on TemplateHaskell and QuasiQuotation] for making an interpolated text QuasiQuoter. Here's another [http://www.well-typed.com/blog/2014/10/quasi-quoting-dsls/ great 2014 blog post on quasiquotation].<br />
<br />
<!-- * [http://www.haskell.org/th/ The old Template Haskell web page]. Would someone feel like moving this material into the HaskellWiki? <br />
--><br />
<!-- * Old and probably not too useful for most but maybe... http://www.cse.unsw.edu.au/~chak/haskell/ghc/comm/exts/th.html <br />
--><br />
* [http://www.cs.ox.ac.uk/people/ian.lynagh/Fraskell/ Fraskell documentation] & explanation of how Template Haskell is used to vastly speed it up.<br />
<br />
* [[Quasiquotation]]<br />
<br />
Feel free to update our Wikipedia entry http://en.wikipedia.org/wiki/Template_Haskell<br />
<br />
= Projects =<br />
<br />
What are you doing/planning to do/have done with Template Haskell?<br />
<br />
* The [http://www.ict.kth.se/org/ict/ecs/sam/projects/forsyde/www ForSyDe methodology] is currently implemented as a Haskell-based DSL which makes extensive use of Template Haskell.<br />
<br />
* I have written a primitive (untyped) binding to the Objective-C runtime system on Mac OS X. It needs just TH, no "stub files" are created, no separate utilities are required. Initial snapshot is at http://www.kfunigraz.ac.at/imawww/thaller/wolfgang/HOC020103.tar.bz2 -- WolfgangThaller<br />
<br />
* I am writing Template Greencard - a reimplementation of GreenCard using TH. Many bits work out really nicely. A few bits didn't work so nicely - once I get some time to think, I'll try to persuade the TH folk to make some changes to fix some of these. -- AlastairReid<br />
<br />
* I'm writing Hacanon - a framework for automatic generation of C++ bindings. Read "automated Template Greencard for C++" (-: Darcs repo: http://www.ScannedInAvian.org/repos/hacanon - You'll need gccxml (http://www.gccxml.org/) to compile the examples. - 27 Dec Lemmih.<br />
<br />
* Following other FFI tools developers, I see some future for Template HSFFIG, especially when it comes to autogenerate peek and poke methods for structures defined in C; may be useful for implementation of certain network protocols such as X11 where layout of messages is provided as C structure/union declaration. - 16 Dec 2005 DimitryGolubovsky<br />
<br />
* I am using Template Haskell as a mechanism to get parsed, typechecked code into an Ajax based Haskell Equational Reasoning tool [[Haskell Equational Reasoning Assistant]], as well as simplify the specification of equational relationships between pieces of code. There was a quicktime movie of the tool being used on http://www.gill-warbington.com/home/andy/share/hera1.html - AndyGill <br />
<br />
* I am working on functional metaprogramming techniques to enhance programming reliability and productivity, by reusing much of the existing compiler technology. Template Haskell is especially interesting for me because it permits to check size information of structures by the compiler, provided this information is available at compile time. This approach is especially appropriate for hardware designs, where the structures are fixed before the circuit starts operating. See our metaprogramming web page at http://www.infosun.fmi.uni-passau.de/cl/metaprog/ -- ChristophHerrmann(http://www.cs.st-and.ac.uk/~ch)<br />
<br />
* I am using Template Haskell to do type safe database access. I initially [http://www.nabble.com/Using-Template-Haskell-to-make-type-safe-database-access-td17027286.html proposed this on haskell-cafe]. I connect to the database at compile-time and let the database do SQL parsing and type inference. The result from parsing and type inference is used to build a type safe database query which can executed at run-time. [[MetaHDBC | You can find the project page here]] -- [mailto:mads_lindstroem@yahoo.dk Mads Lindstrøm]<br />
<br />
= Utilities =<br />
<br />
Helper functions, debugging functions, or more involved code e.g. a monadic fold algebra for TH.Syntax.<br />
<br />
* http://www.haskell.org/pipermail/template-haskell/2003-September/000176.html<br />
<br />
= Known Bugs =<br />
<br />
Take a look at the [http://hackage.haskell.org/trac/ghc/query?status=new&status=assigned&status=reopened&component=Template+Haskell&order=priority open bugs against Template Haskell] on the GHC bug tracker.<br />
<br />
= Wish list =<br />
<br />
Things that Ian Lynagh (Igloo) mentioned in his paper ''Template Haskell: A Report From The Field'' in May 2003 (available [http://www.haskell.org/wikiupload/2/24/Template_Haskell-A_Report_From_The_Field.ps here]), by section:<br />
<br />
* Section 2 (curses)<br />
** The ability to splice names (into "foreign import" declarations, in particular)<br />
** The ability to add things to the export list from a splice(?)<br />
** The ability to use things defined at the toplevel of a module from splices in that same module (would require multi-stage compilation, as opposed to the current approach of expanding splices during typechecking)<br />
<br />
* Section 3 (deriving instances of classes)<br />
** <strike>First-class reification</strike> (the <hask>reify</hask> function)<br />
** A way to discover whether a data constructor was defined infix or prefix (which is necessary to derive instances for <hask>Read</hask> and <hask>Show</hask> as outlined in [http://www.haskell.org/onlinereport/derived.html The Haskell 98 Report: Specification of Derived Instances]) (if there is a way, [http://community.haskell.org/~ndm/derive/ Derive] seems ignorant of it)<br />
** Type/context splicing (in <hask>instance</hask> headers in particular)<br />
<br />
* Section 4 (printf)<br />
** He says something to the effect that a pattern-matching form of the quotation brackets would be cool if it was expressive enough to be useful, but that this would be hard. (Don't expect this anytime soon.)<br />
<br />
* Section 5 (fraskell)<br />
** Type information for quoted code (so that simplification can be done safely even with overloaded operations, like, oh, <hask>(+)</hask>)<br />
<br />
* Section 6 (pan)<br />
** Type info again, and strictness info too (this one seems a bit pie-in-the-sky...)<br />
<br />
(Please leave the implemented ones here, but crossed off.)<br />
<br />
Any other features that may be nice, and TH projects you'd want to see.<br />
<br />
* A TH tutorial (mainly a distillation and update of ''Template Meta-programming in Haskell'' at this point)<br />
* <strike>Write Haddock documentation for the Template Haskell library (http://hackage.haskell.org/trac/ghc/ticket/1576).</strike><br />
* Make `reify` on a class return a list of the instances of that class (http://www.haskell.org/pipermail/template-haskell/2005-December/000503.html). (See also [http://hackage.haskell.org/trac/ghc/ticket/1577 GHC ticket #1577].)<br />
* A set of simple examples on this wiki page<br />
* A TH T-shirt with new logo to wear at conferences<br />
* (Long-term) Unify Language.Haskell.Syntax with Language.Haskell.TH.Syntax so there's just one way to do things (http://hackage.haskell.org/package/haskell-src-meta does a one-way translation, for haskell-src-exts)<br />
<br />
---------------<br />
<br />
= Tips and Tricks =<br />
<br />
== What to do when you can't splice that there ==<br />
<br />
When you try to splice something into the middle of a template and find that you just can't, instead of getting frustrated about it, why not use the template to see what it would look like in longhand? <br />
<br />
First, an excerpt from a module of my own. I, by the way, am SamB.<br />
<haskell><br />
{-# OPTIONS_GHC -fglasgow-exts -fth #-}<br />
<br />
module MMixMemory where<br />
<br />
import Data.Int<br />
import Data.Word<br />
<br />
class (Integral int, Integral word)<br />
=> SignConversion int word | int -> word, word -> int where<br />
<br />
toSigned :: word -> int<br />
toSigned = fromIntegral<br />
toUnsigned :: int -> word<br />
toUnsigned = fromIntegral<br />
<br />
</haskell><br />
<br />
Say I want to find out what I need to do to splice in the types for an instance declaration for the SignConversion class, so that I can declare instances for Int8 with Word8 through Int64 with Word64. So, I start up good-ol' GHCi and do the following:<br />
<br />
<haskell><br />
$ ghci -fth -fglasgow-exts<br />
Prelude> :l MMixMemory<br />
*MMixMemory> :m +Language.Haskell.TH.Syntax<br />
*MMixMemory Language.Haskell.TH.Syntax> runQ [d| instance SignConversion Int Word where |] >>= print<br />
[InstanceD [] (AppT (AppT (ConT MMixMemory.SignConversion) (ConT GHC.Base.Int)) (ConT GHC.Word.Word)) []]<br />
</haskell><br />
<br />
== What can <tt>reify</tt> see? ==<br />
<br />
When you use <tt>reify</tt> to give you information about a <tt>Name</tt>, GHC will tell you what it knows. But sometimes it doesn't know stuff. In particular<br />
<br />
* '''Imported things'''. When you reify an imported function, type constructor, class, etc, from (say) module M, GHC runs off to the interface file <tt>M.hi</tt> in which it deposited all the info it learned when compiling M. However, if you compiled M without optimisation (ie <tt>-O0</tt>, the default), and without <tt>-XTemplateHaskell</tt>, GHC tries to put as little info in the interface file as possible. (This is a possibly-misguided attempt to keep interface files small.) In particular, it may dump only the name and kind of a data type into <tt>M.hi</tt>, but not its constructors.<br />
: Under these circumstances you may reify a data type but get back no information about its data constructors or fields. Solution: compile M with <br />
:* <tt>-O</tt>, or<br />
:* <tt>-fno-omit-interface-pragmas</tt> (implied by -O), or<br />
:* <tt>-XTemplateHaskell</tt>.<br />
<br />
* '''Function definitions'''. The <tt>VarI</tt> constructor of the <tt>Info</tt> type advertises that you might get back the source code for a function definition. In fact, GHC currently (7.4) <em>always</em> returns <tt>Nothing</tt> in this field. It's a bit awkward and no one has really needed it.<br />
<br />
== Why does <tt>runQ</tt> crash if I try to reify something? ==<br />
<br />
This program will fail with an error message when you run it:<br />
<haskell><br />
main = do info <- runQ (reify (mkName "Bool")) -- more hygenic is: (reify ''Bool)<br />
putStrLn (pprint info)<br />
</haskell><br />
Reason: <tt>reify</tt> consults the type environment, and that is not available at run-time. The type of <tt>reify</tt> is <br />
<haskell><br />
reify :: Quasi m => Q a -> m a<br />
</haskell><br />
The IO monad is a poor-man's instance of <tt>Quasi</tt>; it can allocate unique names and gather error messages, but it can't do <tt>reify</tt>. This error should really be caught statically.<br />
<br />
Instead, you can run the splice directly (ex. in ghci -XTemplateHaskell), as the following shows:<br />
<br />
<haskell><br />
GHCi> let tup = $(tupE $ take 4 $ cycle [ [| "hi" |] , [| 5 |] ])<br />
GHCi> :type tup<br />
tup :: ([Char], Integer, [Char], Integer)<br />
<br />
GHCi> tup<br />
("hi",5,"hi",5)<br />
<br />
GHCi> $(stringE . show =<< reify ''Int)<br />
"TyConI (DataD [] GHC.Types.Int [] [NormalC GHC.Types.I# [(NotStrict,ConT GHC.Prim.Int#)]] [])"<br />
</haskell><br />
<br />
Here's an [http://www.haskell.org/pipermail/glasgow-haskell-users/2006-August/010844.html email thread with more details].<br />
<br />
-----------------<br />
<br />
= Examples =<br />
== Tuples ==<br />
=== Select from a tuple ===<br />
<br />
An example to select an element from a tuple of arbitrary size. Taken from [http://research.microsoft.com/en-us/um/people/simonpj/papers/meta-haskell/meta-haskell.pdf this paper].<br />
<br />
Use like so:<br />
<br />
> $(sel 2 3) ('a','b','c')<br />
'b'<br />
> $(sel 3 4) ('a','b','c','d')<br />
'c'<br />
<br />
<br />
<haskell><br />
sel :: Int -> Int -> ExpQ<br />
sel i n = [| \x -> $(caseE [| x |] [alt]) |]<br />
where alt :: MatchQ<br />
alt = match pat (normalB rhs) []<br />
<br />
pat :: Pat<br />
pat = tupP (map varP as)<br />
<br />
rhs :: ExpQ<br />
rhs = varE(as !! (i -1)) -- !! is 0 based<br />
<br />
as :: [String]<br />
as = ["a" ++ show i | i <- [1..n] ]<br />
</haskell><br />
<br />
Alternately:<br />
<br />
<haskell><br />
sel' i n = lamE [pat] rhs<br />
where pat = tupP (map varP as)<br />
rhs = varE (as !! (i - 1))<br />
as = [ "a" ++ show j | j <- [1..n] ]<br />
</haskell><br />
<br />
=== Apply a function to the n'th element ===<br />
<br />
<haskell><br />
tmap i n = do<br />
f <- newName "f"<br />
as <- replicateM n (newName "a")<br />
lamE [varP f, tupP (map varP as)] $<br />
tupE [ if i == i'<br />
then [| $(varE f) $a |]<br />
else a<br />
| (a,i') <- map varE as `zip` [1..] ]<br />
</haskell><br />
<br />
Then tmap can be called as:<br />
<br />
> $(tmap 3 4) (+ 1) (1,2,3,4)<br />
(1,2,4,4)<br />
<br />
=== Convert the first n elements of a list to a tuple ===<br />
<br />
This example creates a tuple by extracting elements from a list. Taken from<br />
[http://www.xoltar.org/2003/aug/13/templateHaskellTupleSample.html www.xoltar.org]<br />
<br />
Use like so:<br />
<br />
> $(tuple 3) [1,2,3,4,5]<br />
(1,2,3)<br />
> $(tuple 2) [1,2]<br />
(1,2)<br />
<br />
<haskell><br />
tuple :: Int -> ExpQ<br />
tuple n = [|\list -> $(tupE (exprs [|list|])) |]<br />
where<br />
exprs list = [infixE (Just (list))<br />
(varE "!!")<br />
(Just (litE $ integerL (toInteger num)))<br />
| num <- [0..(n - 1)]]<br />
</haskell><br />
<br />
An alternative that has more informative errors (a failing pattern match failures give an exact location):<br />
<br />
<haskell><br />
tuple :: Int -> ExpQ<br />
tuple n = do<br />
ns <- replicateM n (newName "x")<br />
lamE [foldr (\x y -> conP '(:) [varP x,y]) wildP ns] (tupE $ map varE ns)<br />
</haskell><br />
<br />
=== Un-nest tuples ===<br />
Convert nested tuples like (a,(b,(c,()))) into (a,b,c) given the length to generate.<br />
<br />
<haskell><br />
unNest n = do<br />
vs <- replicateM n (newName "x")<br />
lamE [foldr (\a b -> tupP [varP a , b])<br />
(conP '() [])<br />
vs]<br />
(tupE (map varE vs))<br />
</haskell><br />
<br />
<br />
<br />
== [[Template Haskell/Marshall Data|Marshall a datatype to and from Dynamic]] ==<br />
This approach is an example of using template haskell to delay typechecking<br />
to be able to abstract out the repeated calls to fromDynamic:<br />
<br />
<haskell><br />
data T = T Int String Double<br />
<br />
toT :: [Dynamic] -> Maybe T<br />
toT [a,b,c] = do<br />
a' <- fromDynamic a<br />
b' <- fromDynamic b<br />
c' <- fromDynamic c<br />
return (T a' b' c')<br />
toT _ = Nothing<br />
</haskell><br />
<br />
== Printf ==<br />
Build it using a command similar to:<br />
<br />
ghc --make Main.hs -o main<br />
<br />
Main.hs:<br />
<br />
<haskell><br />
{-# LANGUAGE TemplateHaskell #-}<br />
<br />
-- Import our template "printf"<br />
import PrintF (printf)<br />
<br />
-- The splice operator $ takes the Haskell source code<br />
-- generated at compile time by "printf" and splices it into<br />
-- the argument of "putStrLn".<br />
main = do<br />
putStrLn $ $(printf "Hello %s %%x%% %d %%x%%") "World" 12<br />
</haskell><br />
<br />
PrintF.hs:<br />
<br />
<haskell><br />
{-# LANGUAGE TemplateHaskell #-}<br />
module PrintF where<br />
<br />
-- NB: printf needs to be in a separate module to the one where<br />
-- you intend to use it.<br />
<br />
-- Import some Template Haskell syntax<br />
import Language.Haskell.TH<br />
<br />
-- Possible string tokens: %d %s and literal strings<br />
data Format = D | S | L String<br />
deriving Show<br />
<br />
-- a poor man's tokenizer<br />
tokenize :: String -> [Format]<br />
tokenize [] = []<br />
tokenize ('%':c:rest) | c == 'd' = D : tokenize rest<br />
| c == 's' = S : tokenize rest<br />
tokenize (s:str) = L (s:p) : tokenize rest -- so we don't get stuck on weird '%'<br />
where (p,rest) = span (/= '%') str<br />
<br />
-- generate argument list for the function<br />
args :: [Format] -> [PatQ]<br />
args fmt = concatMap (\(f,n) -> case f of<br />
L _ -> []<br />
_ -> [varP n]) $ zip fmt names<br />
where names = [ mkName $ 'x' : show i | i <- [0..] ]<br />
<br />
-- generate body of the function<br />
body :: [Format] -> ExpQ<br />
body fmt = foldr (\ e e' -> infixApp e [| (++) |] e') (last exps) (init exps)<br />
where exps = [ case f of<br />
L s -> stringE s<br />
D -> appE [| show |] (varE n)<br />
S -> varE n<br />
| (f,n) <- zip fmt names ]<br />
names = [ mkName $ 'x' : show i | i <- [0..] ]<br />
<br />
-- glue the argument list and body together into a lambda<br />
-- this is what gets spliced into the haskell code at the call<br />
-- site of "printf"<br />
printf :: String -> Q Exp<br />
printf format = lamE (args fmt) (body fmt)<br />
where fmt = tokenize format<br />
</haskell><br />
<br />
== Handling Options with Templates ==<br />
A common idiom for treating a set of options, e.g. from GetOpt, is to define a datatype with all the flags and using a list over this datatype:<br />
<br />
<haskell><br />
data Options = B1 | B2 | V Integer<br />
<br />
options = [B1, V 3]<br />
</haskell><br />
<br />
While it's simple testing if a Boolean flag is set (simply use "elem"), it's harder to check if an option with an argument is set. It's even more tedious writing helper-functions to obtain the value from such an option since you have to explicitely "un-V" each. Here, Template Haskell can be (ab)used to reduce this a bit. The following example provides the module "OptionsTH" which can be reused regardless of the constructors in "Options". Let's start with showing how we'd like to be able to program. Notice that the resulting lists need some more treatment e.g. through "foldl".<br />
<br />
Options.hs:<br />
<br />
<haskell><br />
module Main where<br />
<br />
import OptionsTH<br />
import Language.Haskell.TH.Syntax<br />
<br />
data Options = B1 | B2 | V Int | S String deriving (Eq, Read, Show)<br />
<br />
options = [B1, V 3]<br />
<br />
main = do<br />
print foo -- test if B1 set: [True,False]<br />
print bar -- test if V present, w/o value: [False,True]<br />
print baz -- get value of V if available: [Nothing,Just 3]<br />
<br />
foo :: [Bool]<br />
-- Query constructor B1 which takes no arguments<br />
foo = map $(getopt (THNoArg (mkArg "B1" 0))) options<br />
<br />
bar :: [Bool]<br />
-- V is a unary constructor. Let mkArg generate the required<br />
-- wildcard-pattern "V _".<br />
bar = map $(getopt (THNoArg (mkArg "V" 1))) options<br />
<br />
-- Can't use a wildcard here!<br />
baz :: [(Maybe Int)]<br />
baz = map $(getopt (THArg (conP "V" [varP "x"]))) options<br />
</haskell><br />
<br />
OptionsTH.hs<br />
<br />
<haskell><br />
module OptionsTH where<br />
<br />
import Language.Haskell.TH.Syntax<br />
<br />
-- datatype for querying options:<br />
-- NoArg: Not interested in value (also applies to Boolean flags)<br />
-- Arg: Grep value of unary(!) constructor<br />
data Args = THNoArg Pat | THArg Pat<br />
<br />
getopt :: Args -> ExpQ<br />
getopt (THNoArg pat) = lamE [varP "y"] (caseE (varE "y") [cons0, cons1])<br />
where<br />
cons0 = match pat (normalB [| True |]) []<br />
cons1 = match wildP (normalB [| False |]) []<br />
<br />
-- bind "var" for later use!<br />
getopt (THArg pat@(ConP _ [VarP var])) = lamE [varP "y"] (caseE (varE "y") [cons0, cons1])<br />
where<br />
cons0 = match pat (normalB (appE [|Just|] (varE var))) []<br />
cons1 = match wildP (normalB [|Nothing|]) []<br />
<br />
mkArg :: String -> Int -> Pat<br />
mkArg k c = conP k (replicate c wildP)<br />
</haskell><br />
<br />
While the example might look contrived for the Boolean options which could have been tested much easier, it shows how both types of arguments can be treated in a similar way.<br />
<br />
=== Limitations ===<br />
<tt>getopt (THArg pat)</tt> is only able to treat unary constructors. See the pattern-binding: It matches exactly a single VarP.<br />
<br />
=== Improvements ===<br />
The following reduces things even a bit more, though I still don't know if I like it. It only works since <tt>c</tt> is either 0 or 1.<br />
<br />
<haskell><br />
mkArg k c = conP k (replicate c (varP "x"))<br />
<br />
baz = map $(getopt (THArg (mkArg "V" 1)))<br />
</haskell><br />
-- VolkerStolz<br />
<br />
== Generic constructor for records ==<br />
<br />
I have a large number of record types like this, of different length:<br />
<br />
<haskell><br />
data PGD = PGD {<br />
pgdXUnitBase :: !Word8,<br />
pgdYUnitBase :: !Word8,<br />
pgdXLUnitsperUnitBase :: !Word16<br />
}<br />
</haskell><br />
<br />
Currently I use GHC's Binary module to read them from files; it can handle<br />
types like <tt>(Word8, (Word8, Word16))</tt>, but there was no easy way to generate<br />
the correct amount of "uncurry" calls for automatically grabbing each element.<br />
<br />
With Template Haskell, the instance declarations are now written as such:<br />
<br />
<haskell><br />
instance Binary PGD where<br />
get bh = do a <- get bh ; return $ $(constrRecord PGD) a<br />
</haskell><br />
<br />
Here the trick lies in constrRecord, which is defined as:<br />
<br />
<haskell><br />
constrRecord x = reify exp where<br />
reify = \(Just r) -> appE r $ conE $ last args<br />
exp = foldl (dot) uncur $ replicate terms uncur<br />
terms = ((length args) `div` 2) - 2<br />
dot x y = (Just $ infixE x (varE ".") y)<br />
uncur = (Just [|uncurry|])<br />
args = words . show $ typeOf x<br />
</haskell><br />
<br />
-- AutrijusTang<br />
<br />
== zipWithN ==<br />
<br />
Here $(zipn 3) = zipWith3 etc.<br />
<br />
<haskell><br />
import Language.Haskell.TH; import Control.Applicative; import Control.Monad<br />
<br />
zipn n = do<br />
vs <- replicateM n (newName "vs")<br />
[| \f -><br />
$(lamE (map varP vs)<br />
[| getZipList $<br />
$(foldl<br />
(\a b -> [| $a <*> $b |])<br />
[| pure f |]<br />
(map (\v -> [| ZipList $(varE v) |]) vs))<br />
|])<br />
|]<br />
</haskell><br />
<br />
== 'generic' zipWith ==<br />
A generalization of zipWith to almost any data. Demonstrates the ability to do dynamic binding with TH splices (note 'dyn').<br />
<br />
<haskell><br />
zipCons :: Name -> Int -> [String] -> ExpQ<br />
zipCons tyName ways functions = do<br />
let countFields :: Con -> (Name,Int)<br />
countFields x = case x of<br />
NormalC n (length -> fields) -> (n, fields)<br />
RecC n (length -> fields) -> (n,fields)<br />
InfixC _ n _ -> (n,2)<br />
ForallC _ _ ct -> countFields ct<br />
<br />
TyConI (DataD _ _ _ [countFields -> (c,n)] _) <- reify tyName<br />
when (n /= length functions) $ fail "wrong number of functions named"<br />
vs <- replicateM ways $ replicateM n $ newName "x"<br />
lamE (map (conP c . map varP) vs) $<br />
foldl (\con (vs,f) -><br />
con `appE`<br />
foldl appE<br />
(dyn f)<br />
(map varE vs))<br />
(conE c)<br />
(transpose vs `zip` functions)<br />
</haskell><br />
<br />
This example uses whichever '+' is in scope when the expression is spliced:<br />
<br />
<haskell><br />
:type $(zipCons ''(,,,) 2 (replicate 4 "+"))<br />
<br />
$(zipCons ''(,,,) 2 (replicate 4 "+"))<br />
:: (Num t, Num t1, Num t2, Num t3) =><br />
(t, t1, t2, t3) -> (t, t1, t2, t3) -> (t, t1, t2, t3)<br />
</haskell><br />
<br />
==[[Template haskell/Instance deriving example|Instance deriving example]]==<br />
An example using a 'deriving function' to generate a method instance <br />
per constructor of a type. The deriving function provides the body of the<br />
method.<br />
<br />
Note that this example assumes that the functions of the class take a parameter that is the same type as instance is parameterized with. <br />
<br />
The message [http://www.haskell.org/pipermail/template-haskell/2006-August/000581.html email message] contains the full source ([http://www.iist.unu.edu/~vs/haskell/TH_render.hs extracted file]).<br />
<br />
== [[Quasiquotation|QuasiQuoters]] ==<br />
New in ghc-6.10 is -XQuasiQuotes, which allows one to extend GHC's syntax from library code. Quite a few examples were previously part of older [http://hackage.haskell.org/package/haskell-src-meta-0.2 haskell-src-meta]. Some of these are now part of [http://hackage.haskell.org/package/applicative-quoters applicative-quoters]<br />
<br />
=== Similarity with splices ===<br />
<br />
Quasiquoters used in expression contexts (those using the ''quoteExp'') behave to a first approximation like regular TH splices:<br />
<br />
<haskell><br />
simpleQQ = QuasiQuoter { quoteExp = stringE } -- in another module<br />
<br />
[$simpleQQ| a b c d |] == $(quoteExp simpleQQ " a b c d ")<br />
</haskell><br />
<br />
== Generating records which are variations of existing records ==<br />
This example uses syb to address some of the pain of dealing with the rather large data types. <br />
<br />
<haskell><br />
{-# LANGUAGE ScopedTypeVariables, TemplateHaskell #-}<br />
module A where<br />
import Language.Haskell.TH<br />
import Data.Generics<br />
<br />
addMaybes modName input = let<br />
<br />
rename :: GenericT<br />
rename = mkT $ \n -> if nameModule n == modName<br />
then mkName $ nameBase n ++ "_opt"<br />
else n<br />
<br />
addMaybe :: GenericM Q<br />
addMaybe = mkM $ \(n :: Name, s :: Strict, ty :: Type) -> do<br />
ty' <- [t| Maybe $(return ty) |]<br />
return (n,s,ty')<br />
<br />
in everywhere rename `fmap` everywhereM addMaybe input<br />
<br />
mkOptional :: Name -> Q Dec<br />
mkOptional n = do<br />
TyConI d <- reify n<br />
addMaybes (nameModule n) d<br />
</haskell><br />
<br />
mkOptional then generates a new data type with all Names in that module with an added suffix _opt. Here is an example of its use:<br />
<haskell><br />
{-# LANGUAGE TemplateHaskell #-}<br />
import A<br />
data Foo = Foo { a,b,c,d,e :: Double, f :: Int }<br />
<br />
mapM mkOptional [''Foo]<br />
</haskell><br />
<br />
Generates something like<br />
<haskell><br />
data Foo_opt = Foo_opt {a_opt :: Maybe Double, ..... f_opt :: Maybe Int}<br />
</haskell><br />
<br />
<br />
<br />
[[Category:Language extensions]]</div>Simonpjhttps://wiki.haskell.org/index.php?title=Windows&diff=58381Windows2014-06-27T09:17:15Z<p>Simonpj: /* Quickstart on Windows 7 */</p>
<hr />
<div>== Quickstart on Windows 7 ==<br />
<br />
This page describes what you need to know to ''use'' Haskell on a Windows machine.<br />
See [https://ghc.haskell.org/trac/ghc/wiki/Building/Preparation/Windows the GHC Trac Wiki] for what you need to know to ''build'' GHC on Windows.<br />
<br />
For a minimal setup download the following : <br />
<br />
* [http://sourceforge.net/projects/msys2/ MSYS2] binaries<br />
* [http://www.haskell.org/ghc/download ghc] binaries<br />
* [http://www.haskell.org/cabal/download.html cabal] binaries<br />
<br />
Add the following to the path : <br />
<br />
* <hask>ghc/bin</hask> (should contain <hask>ghc.exe</hask> etc)<br />
* <hask>ghc/mingw/bin</hask> (should contain <hask>gcc.exe</hask> etc)<br />
* <hask>cabal/</hask> (should contain the cabal binary)<br />
<br />
If you launch <hask>msys2_shell.bat</hask> (as opposed to <hask>mingw32_shell.bat</hask> or <hask>mingw64_shell.bat</hask>) then make sure that the following environment variable is defined : <br />
<br />
* <hask>MSYSTEM=MINGW32</hask> or <hask>MSYSTEM=MINGW64</hask><br />
<br />
Then test by firing up either <hask>msys2_shell.bat</hask>, <hask>mingw32_shell.bat</hask>, or <hask>mingw64_shell.bat</hask> and then executing the following sequence of commands : <br />
<br />
* <hask><br />
mkdir test<br />
cd test<br />
cabal sandbox init<br />
cabal install hoogle<br />
</hask><br />
<br />
Note that the absence of the environment variables above will result in linker errors when building hoogle.<br />
<br />
== Editors ==<br />
<br />
* [http://www.e-texteditor.com/ E-Text Editor (TextMate for Windows)]<br />
* [http://www.textpad.com/ TextPad]<br />
* [http://ftp.gnu.org/gnu/emacs/windows/ Emacs], [http://www.vim.org/ Vi(m)], etc<br />
* [http://www.leksah.org/index.html Leksah]: Haskell IDE written in Haskell<br />
* [http://eclipsefp.sourceforge.net/ Eclipse]<br />
* [http://notepad-plus-plus.org/ Notepad++]<br />
* [http://www.sublimetext.com/ Sublime Text]<br />
* [http://www.pnotepad.org/ Programmer's Notepad]<br />
<br />
== Compilers/interpreters ==<br />
<br />
* [http://www.haskell.org/platform/ The Haskell Platform] is a combination of GHC and a set of blessed libraries<br />
* [[WinHugs]]<br />
* [[GHC]]: Special notes for Cygwin users - [http://www.haskell.org/ghc/docs/6.6/html/building/platforms.html] [http://www.haskell.org/ghc/docs/latest/html/users_guide/ghci-cygwin.html]<br />
* [http://code.google.com/p/winghci/ WinGhci], a GUI for GHCi (included in the Haskell Platform)<br />
<br />
== Tools for compilation ==<br />
<br />
* As some of the packages contain Unix/Linux specific scripts/commands, you need [http://www.mingw.org/ MinGW] and [http://www.mingw.org/wiki/msys MSYS] to simulate a Unix environment. In some cases you need [http://www.cygwin.com/ Cygwin] instead. If you use [http://code.google.com/p/msysgit/ msysgit] on Windows already, all you need to do is add MinGW to your path.<br />
<br />
* If you need to link to C-software, [http://en.wikipedia.org/wiki/Environment_variable#DOS.2C_OS.2F2_and_Windows_.28Command_Prompt.29 define environment variable] C_INCLUDE_PATH that lists the directories where the header files can be found, for example:<br />
Set C_INCLUDE_PATH=C:\usr\local\include;C:\usr\local\include\SDL<br />
:(It is advisable to use paths without spaces, because some scripts in the MinGW/MSYS environment have problems with spaces in paths.)<br><br />
:For linking the libraries, you need to define environment variable LIBRARY_PATH as well, listing the directories where .a and .lib files can be found. In case C++ software must be compiled, define CPLUS_INCLUDE_PATH to list the directories with C++ header files.<br />
<br />
* Packages are often delivered as a .tar or .tar.gz file, see [[How to unpack a tar file in Windows]]<br />
<br />
* To work with/produce DLL files with GHC < 7.0.1, you need dlltool.exe, from the [http://sourceforge.net/projects/mingw/files/ mingw-binutils] package and pexports.exe from the [http://sourceforge.net/projects/mingw/files/ mingw-utils] package. For more information see [http://www.cse.yorku.ca/tdb/_doc.php/userg/man/name/dlltool/section/1 the dlltool manual] and [http://www.willus.com/mingw/yongweiwu_stdcall.html Stdcall and DLL tools of MSVC and MinGW]<br />
: If you have GHC >= 7.0.1, see [http://www.haskell.org/ghc/docs/latest/html/users_guide/using-shared-libs.html Using shared libraries] or [http://www.haskell.org/ghc/docs/latest/html/users_guide/win32-dlls.html Building and using Win32 DLLs]<br />
<br />
== Libraries ==<br />
<br />
* GUI : [[wxHaskell]] - A binding of wxWidgets (formerly known as wxWindows) in Haskell. Note: see also [[wxHaskell/Windows]]<br />
<br />
* GUI : [[Gtk2Hs]] - A binding of GTK+ in Haskell. Note: this requires installing [http://www.gtk.org GTK+] on windows.<br />
<br />
* [http://hackage.haskell.org/cgi-bin/hackage-scripts/package/Win32 Win32] - low levelish bindings to Windows API. Comes with GHC and non-minimal Hugs distribution. [https://github.com/haskell/win32 Win32 git repo]<br />
<br />
* [[HDBC-ODBC under Windows]] for database access.<br />
<br />
* [http://hackage.haskell.org/cgi-bin/hackage-scripts/package/winerror winerror]: Error handling for foreign calls to the Windows API<br />
<br />
== Special tips and tricks for Windows ==<br />
<br />
* If there are DLLs missing from your environment, you can find out which, using [http://cygwin.com/cygwin-ug-net/using-utils.html cygcheck] from the [http://www.cygwin.com/ Cygwin project]. Note, that you will get problems if you have both MinGW and Cygwin in your search path; it is best to specify the full path to cygcheck.exe, or copy cygcheck.exe to some location in the search path.<br />
: Another option is [http://www.dependencywalker.com/ Dependency Walker]; this tool can also be used to find out, in which DLL a crash occurs.<br />
<br />
* [http://www.haskell.org/pipermail/haskell-cafe/2013-February/106436.html Terminal Win32/Building Haskeline/8.3 file issue] (Haskell-cafe)<br />
<br />
* darcs : http://wiki.darcs.net/WindowsConfiguration<br />
<br />
* Make sure your Haskell compiler (e.g. GHC) and tools are on your system path: http://www.computerhope.com/issues/ch000549.htm<br />
<br />
* Instead of using WinGHCi, one can also run GHCi in shell mode in Emacs &mdash; do 'M-x shell' in Emacs, then type 'ghci'.<br />
<br />
* GHCi on Cygwin: When running GHC under a Cygwin shell on Windows, Ctrl-C sometimes doesn't work. A workaround is to use the rlwrap program to invoke GHCi : In addition to proper Ctrl-C, you also get Emacs (or vi) key bindings and command history across sessions, which saves you a load of typing.<br />
<br />
* If a package depends (either directly or indirectly) on the <code>unix</code> package, you cannot compile it on Windows.<br />
:A simple way to see, if a package X depends on <code>unix</code>, is giving the command:<br />
cabal install X --dry-run<br />
:This will list all packages that would be installed<br />
<br />
* If you are missing or need to distribute libraries with an application, the correct place to put them is *NOT* in \WINDOWS\System32 as once was the practice in the early days of Windows. All sane applications/installers keep their own private dependencies in the application directory. E.g., if the user has chosen to install your application to C:\Program Files\Foo then it is best to install any DLLs in the same location.<br />
<br />
* When compiling a program with GUI, use the compiler option -optl-mwindows to prevent a DOS-shell being displayed behind your GUI. (This passes the option -mwindows to the linker.)<br />
<br />
* Source files from Unix(-like) systems have lines terminated with Line Feed only; if your favorite editor cannot handle this, you can convert the files to MS-DOS format with the <code>unix2dos</code> command (from the [http://sourceforge.net/projects/mingw/files/ mingw-utils] package). For more information, give command: <code>unix2dos --help</code><br />
:Note, that GHC can handle source files in Unix format.<br />
<br />
* To convert a set of files to MS-DOS format (note: this might damage binary files):<br />
::<code>C:\MSYS\1.0\bin\find . -type f -exec unix2dos {} ;</code><br />
:Note: the <code>find</code> command included in MSYS is different from the MS-DOS <code>find</code> command, therefore, you need to specify the entire path to this command.<br />
<br />
== Binary downloads ==<br />
<br />
=== Haskell ===<br />
<br />
Below a list of binary packages for Windows. To be sure you get the most recent version of each, it is best to download the source from [http://hackage.haskell.org/packages/archive/pkg-list.html Hackage] and compile (except for the Haskell Platform).<br />
<br />
* [http://www.haskell.org/platform/windows.html The Haskell Platform] [[Haskell Platform | (HaskellWiki page)]], contains GHC and a set of libraries and tools <br />
* [http://www.haskell.org/ghc/dist/7.6.3/ghc-7.6.3-i386-unknown-mingw32.tar.bz2 GHC 7.6.3 for Windows x86], [http://www.haskell.org/ghc/dist/7.6.3/ghc-7.6.3-x86_64-unknown-mingw32.tar.bz2 GHC 7.6.3 for Windows 64bit] [[GHC | (HaskellWiki page)]]<br />
* [http://leksah.org/download.html Leksah] [[Leksah | (HaskellWiki page)]]<br />
* [http://darcs.net/Binaries Darcs] [[Darcs | (HaskellWiki page)]]<br />
* [http://repetae.net/computer/haskell/DrIFT/drop/ Drift] [http://repetae.net/computer/haskell/DrIFT/ (website)] <br />
* [http://www.haskell.org/haddock/haddock-0.7-Win32.zip Haddock 0.7] (obsolete) [http://www.haskell.org/haddock/ (website)] <br />
* [http://www.haskell.org/happy/dist/1.13/happy-1-13.msi Happy 1.13] (obsolete) [http://www.haskell.org/happy/ (website)] <br />
* [ftp://ftp.cs.york.ac.uk/pub/haskell/contrib/hscolour-1.9.zip HsColour 1.9] [http://www.cs.york.ac.uk/fp/darcs/hscolour/ (website)] <br />
* [http://cvs.haskell.org/Hugs/pages/downloading.htm WinHugs September 2006] [http://www.haskell.org/hugs/ (website)] <br />
* [http://haskell.forkio.com/Home/curl-win32/curl-7.19.4-mingw32.zip?attredirects=0 cURL 7.19.4] [http://haskell.forkio.com/Home/curl-win32/ (website)]<br />
<br />
=== Development ===<br />
<br />
[https://ghc.haskell.org/trac/ghc/wiki/Building/Preparation/Windows Setting up a Windows system for building GHC]<br />
<br />
== Shipping Installable Applications ==<br />
<br />
* [http://hackage.haskell.org/cgi-bin/hackage-scripts/package/bamse bamse] lets you build windows installers for your Haskell app (MSI).<br />
* [http://www.jrsoftware.org/isinfo.php Inno Setup] is another tool to create windows installers.<br />
* [http://wixtoolset.org/ WiX Toolset], builds Windows installation packages from XML source code<br />
* [http://zero-install.sourceforge.net/ Zero Install] creates packages for several platforms ("a decentralised cross-distribution software installation system")<br />
<br />
[[Category:OS]]</div>Simonpjhttps://wiki.haskell.org/index.php?title=Tutorials&diff=57992Tutorials2014-05-01T07:41:56Z<p>Simonpj: /* Other tutorials */</p>
<hr />
<div>==Introductions to Haskell==<br />
<br />
These are the recommended places to start learning, short of buying a [[Books#Textbooks|textbook]].<br />
<br />
=== Best places to start ===<br />
<br />
;[http://learnyouahaskell.com Learn You a Haskell for Great Good! (LYAH)]<br />
: Nicely illustrated tutorial showing Haskell concepts while interacting in GHCi. Written and drawn by Miran Lipovača.<br />
<br />
;[http://book.realworldhaskell.org/ Real World Haskell (RWH)]<br />
: A free online version of the complete book, with numerous reader-submitted comments. RWH is best suited for people who know the fundamentals of Haskell already, and can write basic Haskell programs themselves already. It makes a great follow up after finishing LYAH. It can easily be read cover-to-cover, or you can focus on the chapters that interest you most, or when you find an idea you don't yet understand.<br />
<br />
;[http://en.wikibooks.org/wiki/Haskell/YAHT Yet Another Haskell Tutorial (YAHT)]<br />
:By Hal Daume III et al. A recommended tutorial for Haskell that is still under construction but covers already much ground. Also a classic text.<br />
<br />
;[http://en.wikibooks.org/wiki/Haskell Haskell Wikibook] <br />
:A communal effort by several authors to produce the definitive Haskell textbook. It's very much a work in progress at the moment, and contributions are welcome. For 6 inch e-Readers/tablet computers, there is [http://commons.wikimedia.org/wiki/File:Haskell_eBook_Reader.pdf a PDF version of the book]. <br />
<br />
;[http://en.wikibooks.org/wiki/Write_Yourself_a_Scheme_in_48_Hours Write Yourself a Scheme in 48 Hours in Haskell]<br />
:A Haskell Tutorial, by Jonathan Tang. Most Haskell tutorials on the web seem to take a language-reference-manual approach to teaching. They show you the syntax of the language, a few language constructs, and then have you construct a few simple functions at the interactive prompt. The "hard stuff" of how to write a functioning, useful program is left to the end, or sometimes omitted entirely. This tutorial takes a different tack. You'll start off with command-line arguments and parsing, and progress to writing a fully-functional Scheme interpreter that implements a good-sized subset of R5RS Scheme. Along the way, you'll learn Haskell's I/O, mutable state, dynamic typing, error handling, and parsing features. By the time you finish, you should be fairly fluent in both Haskell and Scheme.<br />
<br />
;[http://acm.wustl.edu/functional/haskell.php How to Learn Haskell]<br />
:Some students at Washington University in St. Louis documented the path they took to learning Haskell and put together a nice meta-tutorial to guide beginners through some of the available resources. Experienced programmers looking for some quick code examples may be interested in their [http://acm.wustl.edu/functional/hs-breads.php breadcrumbs].<br />
<br />
;[http://ohaskell.ru/ О Haskell по-человечески]<br />
:About Haskell from a beginner for beginners. Not an academical, but practical tutorial. Written by Denis Shevchenko in Russian.<br />
<br />
=== Other tutorials ===<br />
<br />
;[http://dev.stephendiehl.com/hask/ What I wish I knew when learning Haskell] :By Stephen Diehl. Does what it says on the tin. See [http://www.reddit.com/r/haskell/comments/23srcm/what_i_wish_i_knew_when_learning_haskell_20/ Reddit appreciation]<br />
<br />
;[http://www.yellosoft.us/evilgenius/ Haskell for the Evil Genius] :By Andrew Pennebaker. An overview of how functional and declarative programming can increase the accuracy and efficiency of digital superweapons, empowering evil geniuses in their supreme goal of taking over the world.<br />
<br />
;[http://www.yellosoft.us/parallel-processing-with-haskell Parallel Processing with Haskell] :By Andrew Pennebaker. A short, accelerated introduction to Haskell for coding parallel programs.<br />
<br />
;[http://www.yellosoft.us/getoptfu GetOptFu] :By Andrew Pennebaker. A guide to robust command line argument parsing in Haskell. Available online in HTML, and offline in ePUB and MOBI formats.<br />
<br />
;[http://www.haskell.org/tutorial/ A [[Gentle]] Introduction to Haskell] :By Paul Hudak, John Peterson, and Joseph H. Fasel. The title is misleading. Some knowledge of another functional programming language is expected. The emphasis is on the type system and those features which are really new in Haskell (compared to other functional programming languages). A classic, but not for the faint of heart (it's not so gentle). Also available in [http://www.haskell.org/wikiupload//5/5e/GentleFR.pdf French] [http://gorgonite.developpez.com/livres/traductions/haskell/gentle-haskell/ from this website] and also [http://www.rsdn.ru/article/haskell/haskell_part1.xml in Russian]. <br />
<br />
;[[H-99: Ninety-Nine Haskell Problems]]<br />
:A collection of programming puzzles, with Haskell solutions. Solving these is a great way to get into Haskell programming.<br />
<br />
;[http://shuklan.com/haskell Undergraduate Haskell Lectures from the University of Virginia] <br />
:An introductory set of slides full of example code for an undergraduate course in Haskell. Topics include basic list manipulations, higher order functions, cabal, the IO Monad, and Category Theory.<br />
<br />
;[[Haskell Tutorial for C Programmers]]<br />
:By Eric Etheridge. From the intro: "This tutorial assumes that the reader is familiar with C/C++, Python, Java, or Pascal. I am writing for you because it seems that no other tutorial was written to help students overcome the difficulty of moving from C/C++, Java, and the like to Haskell."<br />
<br />
;[http://www.ibm.com/developerworks/linux/tutorials/l-hask/ Beginning Haskell] <br />
:From IBM developerWorks. This tutorial targets programmers of imperative languages wanting to learn about functional programming in the language Haskell. If you have programmed in languages such as C, Pascal, Fortran, C++, Java, Cobol, Ada, Perl, TCL, REXX, JavaScript, Visual Basic, or many others, you have been using an imperative paradigm. This tutorial provides a gentle introduction to the paradigm of functional programming, with specific illustrations in the Haskell 98 language. (Free registration required.)<br />
<br />
;[http://www.cse.chalmers.se/~rjmh/tutorials.html Tutorial Papers in Functional Programming].<br />
:A collection of links to other Haskell tutorials, from John Hughes.<br />
<br />
;[http://www.cs.ou.edu/~rlpage/fpclassCurrent/textbook/haskell.shtml Two Dozen Short Lessons in Haskell] <br />
:By Rex Page. A draft of a textbook on functional programming, available by ftp. It calls for active participation from readers by omitting material at certain points and asking the reader to attempt to fill in the missing information based on knowledge they have already acquired. The missing information is then supplied on the reverse side of the page. <br />
<br />
;[ftp://ftp.geoinfo.tuwien.ac.at/navratil/HaskellTutorial.pdf Haskell-Tutorial] <br />
:By Damir Medak and Gerhard Navratil. The fundamentals of functional languages for beginners. <br />
<br />
;[http://video.s-inf.de/#FP.2005-SS-Giesl.(COt).HD_Videoaufzeichnung Video Lectures] <br />
:Lectures (in English) by Jürgen Giesl. About 30 hours in total, and great for learning Haskell. The lectures are 2005-SS-FP.V01 through 2005-SS-FP.V26. Videos 2005-SS-FP.U01 through 2005-SS-FP.U11 are exercise answer sessions, so you probably don't want those.<br />
<br />
;[http://www.cs.utoronto.ca/~trebla/fp/ Albert's Functional Programming Course] <br />
:A 15 lesson introduction to most aspects of Haskell.<br />
<br />
;[http://www.iceteks.com/articles.php/haskell/1 Introduction to Haskell]<br />
:By Chris Dutton, An "attempt to bring the ideas of functional programming to the masses here, and an experiment in finding ways to make it easy and interesting to follow".<br />
<br />
;[http://www.csc.depauw.edu/~bhoward/courses/0203Spring/csc122/haskintro/ An Introduction to Haskell]<br />
:A brief introduction, by Brian Howard.<br />
<br />
;[http://www.linuxjournal.com/article/9096 Translating Haskell into English]<br />
:By Shannon Behrens, a glimpse of the Zen of Haskell, without requiring that they already be Haskell converts.<br />
<br />
;[http://www.shlomifish.org/lecture/Perl/Haskell/slides/ Haskell for Perl Programmers]<br />
:Brief introduction to Haskell, with a view to what perl programmers are interested in<br />
<br />
;[http://lisperati.com/haskell/ How To Organize a Picnic on a Computer]<br />
:Fun introduction to Haskell, step by step building of a program to seat people at a planned picnic, based on their similarities using data from a survey and a map of the picnic location.<br />
<br />
;[http://cs.wallawalla.edu/research/KU/PR/Haskell.html Haskell Tutorial]<br />
<br />
;[http://www.lisperati.com/haskell/ Conrad Barski's Haskell tutorial .. with robots]<br />
<br />
;[[Media:Introduction.pdf|Frederick Ross's Haskell introduction]]<br />
<br />
;[http://de.wikibooks.org/wiki/Haskell Dirk's Haskell Tutorial]<br />
:in German for beginners by a beginner. Not so deep, but with a lot examples with very small steps.<br />
<br />
;[http://www.crsr.net/Programming_Languages/SoftwareTools/index.html Software Tools in Haskell]<br />
:A tutorial for advanced readers<br />
<br />
== Motivation for using Haskell ==<br />
<br />
;[http://www.cse.chalmers.se/~rjmh/Papers/whyfp.html Why Functional Programming Matters] <br />
:By [http://www.cse.chalmers.se/~rjmh/ John Hughes], The Computer Journal, Vol. 32, No. 2, 1989, pp. 98 - 107. Also in: David A. Turner (ed.): Research Topics in Functional Programming, Addison-Wesley, 1990, pp. 17 - 42.<BR> Exposes the advantages of functional programming languages. Demonstrates how higher-order functions and lazy evaluation enable new forms of modularization of programs.<br />
<br />
;[[Why Haskell matters]] <br />
:Discussion of the advantages of using Haskell in particular. An excellent article.<br />
<br />
;[http://www.youtube.com/watch?v=Fqi0Xu2Enaw Haskell Introduction]<br />
:A video from FP Complete<br />
<br />
;[http://www.cs.kent.ac.uk/pubs/1997/224/index.html Higher-order + Polymorphic = Reusable] <br />
:By [http://www.cs.kent.ac.uk/people/staff/sjt/index.html Simon Thompson]. Unpublished, May 1997.<BR> <STRONG>Abstract:</STRONG> This paper explores how certain ideas in object oriented languages have their correspondents in functional languages. In particular we look at the analogue of the iterators of the C++ standard template library. We also give an example of the use of constructor classes which feature in Haskell 1.3 and Gofer.<br />
<br />
;[http://www.ibm.com/developerworks/java/library/j-cb07186/index.html Explore functional programming with Haskell]<br />
:Introduction to the benefits of functional programming in Haskell by Bruce Tate.<br />
<br />
== Blog articles ==<br />
<br />
There are a large number of tutorials covering diverse Haskell topics<br />
published as blogs. Some of the best of these articles are collected<br />
here:<br />
<br />
;[[Blog articles]]<br />
<br />
==Practical Haskell==<br />
<br />
These tutorials examine using Haskell to writing complex real-world applications<br />
<br />
;[http://research.microsoft.com/en-us/um/people/simonpj/Papers/marktoberdorf/ Tackling the awkward squad: monadic input/output, concurrency, exceptions, and foreign-language calls in Haskell]<br />
:Simon Peyton Jones. Presented at the 2000 Marktoberdorf Summer School. In "Engineering theories of software construction", ed Tony Hoare, Manfred Broy, Ralf Steinbruggen, IOS Press, ISBN 1-58603-1724, 2001, pp47-96. The standard reference for monadic IO in GHC/Haskell. <br><strong>Abstract:</strong>Functional programming may be beautiful, but to write real applications we must grapple with awkward real-world issues: input/output, robustness, concurrency, and interfacing to programs written in other languages.<br />
<br />
;[[Hitchhikers Guide to the Haskell]]<br />
: Tutorial for C/Java/OCaml/... programers by Dmitry Astapov. From the intro: "This text intends to introduce the reader to the practical aspects of Haskell from the very beginning (plans for the first chapters include: I/O, darcs, Parsec, QuickCheck, profiling and debugging, to mention a few)".<br />
<br />
;[http://www.haskell.org/haskellwiki/IO_inside Haskell I/O inside: Down the Rabbit's Hole]<br />
:By Bulat Ziganshin (2006), a comprehensive tutorial on using IO monad.<br />
<br />
;[http://web.archive.org/web/20060622030538/http://www.reid-consulting-uk.ltd.uk/docs/ffi.html A Guide to Haskell's Foreign Function Interface]<br />
:A guide to using the foreign function interface extension, using the rich set of functions in the Foreign libraries, design issues, and FFI preprocessors.<br />
<br />
;[[Haskell IO for Imperative Programmers]]<br />
:A short introduction to IO from the perspective of an imperative programmer.<br />
<br />
;[[A brief introduction to Haskell|A Brief Introduction to Haskell]]<br />
:A translation of the article, [http://www.cs.jhu.edu/~scott/pl/lectures/caml-intro.html Introduction to OCaml], to Haskell.<br />
<br />
;[[Roll your own IRC bot]]<br />
:This tutorial is designed as a practical guide to writing real world code in Haskell and hopes to intuitively motivate and introduce some of the advanced features of Haskell to the novice programmer, including monad transformers. Our goal is to write a concise, robust and elegant IRC bot in Haskell.<br />
<br />
;[http://projects.haskell.org/gtk2hs/docs/tutorial/glade/ Glade Tutorial (GUI Programming)]<br />
:For the absolute beginner in both Glade and Gtk2Hs. Covers the basics of Glade and how to access a .glade file and widgets in Gtk2Hs. Estimated learning time: 2 hours.<br />
;[http://www.muitovar.com/glade/es-index.html Tutorial de Glade]<br />
:A Spanish translation of the Glade tutorial<br />
<br />
;[http://www.muitovar.com/gtk2hs/index.html Gtk2Hs Tutorial]<br />
: An extensive [[Gtk2Hs]] programming guide, based on the GTK+2.0 tutorial by Tony Gale and Ian Main. This tutorial on GUI programming with Gtk2Hs has 22 chapters in 7 sections, plus an appendix on starting drawing with Cairo. A Spanish translation and source code of the examples are also available.<br />
<br />
;Applications of Functional Programming<br />
:Colin Runciman and David Wakeling (ed.), UCL Press, 1995, ISBN 1-85728-377-5 HB. From the cover:<blockquote>This book is unique in showcasing real, non-trivial applications of functional programming using the Haskell language. It presents state-of-the-art work from the FLARE project and will be an invaluable resource for advanced study, research and implementation.</blockquote><br />
<br />
;[[DealingWithBinaryData]] a guide to ByteStrings, the various <tt>Get</tt> monads and the <tt>Put</tt> monad.<br />
<br />
;[[Internationalization of Haskell programs]]<br />
:Short tutorial on how to use GNU gettext utility to make applications, written on Haskell, multilingual.<br />
<br />
===Testing===<br />
<br />
;[http://blog.moertel.com/articles/2006/10/31/introductory-haskell-solving-the-sorting-it-out-kata Small overview of QuickCheck]<br />
<br />
;[[Introduction to QuickCheck]]<br />
<br />
==Reference material==<br />
<br />
;[http://www.haskell.org/haskellwiki/Category:Tutorials A growing list of Haskell tutorials on a diverse range of topics]<br />
:Available on this wiki<br />
<br />
;[http://www.haskell.org/haskellwiki/Category:How_to "How to"-style tutorials and information]<br />
<br />
;[http://zvon.org/other/haskell/Outputglobal/index.html Haskell Reference] <br />
:By Miloslav Nic.<br />
<br />
;[http://members.chello.nl/hjgtuyl/tourdemonad.html A tour of the Haskell Monad functions]<br />
:By Henk-Jan van Tuyl.<br />
<br />
;[http://www.cse.unsw.edu.au/~en1000/haskell/inbuilt.html Useful Haskell functions]<br />
:An explanation for beginners of many Haskell functions that are predefined in the Haskell Prelude.<br />
<br />
;[http://www.haskell.org/ghc/docs/latest/html/libraries/ Documentation for the standard libraries]<br />
:Complete documentation of the standard Haskell libraries.<br />
<br />
;[http://www.haskell.org/haskellwiki/Category:Idioms Haskell idioms]<br />
:A collection of articles describing some common Haskell idioms. Often quite advanced.<br />
<br />
;[http://www.haskell.org/haskellwiki/Blow_your_mind Useful idioms]<br />
:A collection of short, useful Haskell idioms.<br />
<br />
;[http://www.haskell.org/haskellwiki/Programming_guidelines Programming guidelines]<br />
:Some Haskell programming and style conventions.<br />
<br />
;[http://www.cse.chalmers.se/~rjmh/Combinators/LightningTour/index.htm Lightning Tour of Haskell]<br />
:By John Hughes, as part of a Chalmers programming course<br />
<br />
;[http://vmg.pp.ua/books/КопьютерыИсети/_ИХТИК31G/single/Hall%20C.The%20little%20Haskeller.pdf The Little Haskeller] <br />
:By Cordelia Hall and John Hughes. 9. November 1993, 26 pages. An introduction using the Chalmers Haskell B interpreter (hbi). Beware that it relies very much on the user interface of hbi which is quite different for other Haskell systems, and the tutorials cover Haskell 1.2 , not Haskell 98.<br />
<br />
;[http://www.staff.science.uu.nl/~fokke101/courses/fp-eng.pdf Functional Programming]<br />
:By Jeroen Fokker, 1995. (153 pages, 600 KB). Textbook for learning functional programming with Gofer (an older implementation of Haskell). Here without Chapters&nbsp;6 and&nbsp;7.<br />
<br />
== Comparisons to other languages ==<br />
<br />
Articles contrasting feature of Haskell with other languages.<br />
<br />
;[http://programming.reddit.com/goto?id=nq1k Haskell versus Scheme]<br />
:Mark C. Chu-Carroll, Haskell and Scheme: Which One and Why?<br />
<br />
;[http://wiki.python.org/moin/PythonVsHaskell Comparing Haskell and Python]<br />
:A short overview of similarities and differences between Haskell and Python.<br />
<br />
;[http://programming.reddit.com/goto?id=nwm2 Monads in OCaml]<br />
:Syntax extension for monads in OCaml<br />
<br />
;[http://www.shlomifish.org/lecture/Perl/Haskell/slides/ Haskell for Perl programmers]<br />
:Short intro for perlers<br />
<br />
;[[A_brief_introduction_to_Haskell|Introduction to Haskell]] versus [http://www.cs.jhu.edu/~scott/pl/lectures/caml-intro.html Introduction to OCaml].<br />
<br />
;[http://www.thaiopensource.com/relaxng/derivative.html An algorithm for RELAX NG validation]<br />
:by James Clark (of RELAX NG fame). Describes an algorithm for validating an XML document against a RELAX NG schema, uses Haskell to describe the algorithm. The algorithm in Haskell and Java is then [http://www.donhopkins.com/drupal/node/117 discussed here].<br />
<br />
;[http://blog.prb.io/first-steps-with-haskell-for-web-applications.html Haskell + FastCGI versus Ruby on Rails]<br />
:A short blog entry documenting performance results with ruby on rails and Haskell with fastcgi<br />
<br />
;[http://haskell.cs.yale.edu/wp-content/uploads/2011/03/HaskellVsAda-NSWC.pdf Haskell vs. Ada vs. C++ vs. Awk vs. ..., An Experiment in Software Prototyping Productivity] (PDF)<br />
:Paul Hudak and Mark P. Jones, 16 pages.<blockquote>Description of the results of an experiment in which several conventional programming languages, together with the functional language Haskell, were used to prototype a Naval Surface Warfare Center requirement for Geometric Region Servers. The resulting programs and development metrics were reviewed by a committee chosen by the US Navy. The results indicate that the Haskell prototype took significantly less time to develop and was considerably more concise and easier to understand than the corresponding prototypes written in several different imperative languages, including Ada and C++. </blockquote> <br />
<br />
;[http://www.osl.iu.edu/publications/prints/2003/comparing_generic_programming03.pdf A Comparative Study of Language Support for Generic Programming] (pdf)<br />
:Ronald Garcia, Jaakko Jrvi, Andrew Lumsdaine, Jeremy G. Siek, and Jeremiah Willcock. In Proceedings of the 2003 ACM SIGPLAN conference on Object-oriented programming, systems, languages, and applications (OOPSLA'03), October 2003.<blockquote>An interesting comparison of generic programming support across languages, including: Haskell, SML, C++, Java, C#. Haskell supports all constructs described in the paper -- the only language to do so. </blockquote><br />
<br />
;[http://homepages.inf.ed.ac.uk/wadler/realworld/index.html Functional Programming in the Real World]<br />
:A list of functional programs applied to real-world tasks. The main criterion for being real-world is that the program was written primarily to perform some task, not primarily to experiment with functional programming. Functional is used in the broad sense that includes both `pure' programs (no side effects) and `impure' (some use of side effects). Languages covered include CAML, Clean, Erlang, Haskell, Miranda, Scheme, SML, and others.<br />
<br />
;[http://www.defmacro.org/ramblings/lisp-in-haskell.html Lisp in Haskell]<br />
:Writing A Lisp Interpreter In Haskell, a tutorial<br />
<br />
;[http://bendyworks.com/geekville/articles/2012/12/from-ruby-to-haskell-part-1-testing From Ruby to Haskell, Part 1: Testing]<br />
:A quick comparison between ruby's and haskell's BDD.<br />
<br />
== Teaching Haskell ==<br />
<br />
;[http://www.cs.kent.ac.uk/pubs/1997/208/index.html Where do I begin? A problem solving approach to teaching functional programming]<br />
:By [http://www.cs.kent.ac.uk/people/staff/sjt/index.html Simon Thompson]. In Krzysztof Apt, Pieter Hartel, and Paul Klint, editors, First International Conference on Declarative Programming Languages in Education. Springer-Verlag, September 1997. <br> <STRONG>Abstract:</STRONG> This paper introduces a problem solving method for teaching functional programming, based on Polya's `How To Solve It', an introductory investigation of mathematical method. We first present the language independent version, and then show in particular how it applies to the development of programs in Haskell. The method is illustrated by a sequence of examples and a larger case study. <br />
<br />
;[http://www.cs.kent.ac.uk/pubs/1995/214/index.html Functional programming through the curriculum]<br />
:By [http://www.cs.kent.ac.uk/people/staff/sjt/index.html Simon Thompson] and Steve Hill. In Pieter H. Hartel and Rinus Plasmeijer, editors, Functional Programming Languages in Education, LNCS 1022, pages 85-102. Springer-Verlag, December 1995. <br> <STRONG>Abstract:</STRONG> This paper discusses our experience in using a functional language in topics across the computer science curriculum. After examining the arguments for taking a functional approach, we look in detail at four case studies from different areas: programming language semantics, machine architectures, graphics and formal languages. <br />
<br />
;[http://www.cse.unsw.edu.au/~chak/papers/CK02a.html The Risks and Benefits of Teaching Purely Functional Programming in First Year]<br />
:By [http://www.cse.unsw.edu.au/~chak/ Manuel M. T. Chakravarty] and [http://www.cse.unsw.edu.au/~keller/ Gabriele Keller]. Journal of Functional Programming 14(1), pp 113-123, 2004. An earlier version of this paper was presented at Functional and Declarative Programming in Education (FDPE02). <br> <strong>Abstract</strong> We argue that teaching purely functional programming as such in freshman courses is detrimental to both the curriculum as well as to promoting the paradigm. Instead, we need to focus on the more general aims of teaching elementary techniques of programming and essential concepts of computing. We support this viewpoint with experience gained during several semesters of teaching large first-year classes (up to 600 students) in Haskell. These classes consisted of computer science students as well as students from other disciplines. We have systematically gathered student feedback by conducting surveys after each semester. This article contributes an approach to the use of modern functional languages in first year courses and, based on this, advocates the use of functional languages in this setting.<br />
<br />
<br />
==Using monads==<br />
<br />
;[http://www.haskell.org/wikiupload/c/c6/ICMI45-paper-en.pdf How to build a monadic interpreter in one day] (PDF)<br />
:By Dan Popa. A small tutorial on how to build a language in one day, using the Parser Monad in the front end and a monad with state and I/O string in the back end. Read it if you are interested in learning: <br />
:# language construction and <br />
:# interpreter construction<br />
<br />
;[[Monad Transformers Explained]]<br />
<br />
;[[MonadCont under the hood]]<br />
:A detailed description of the ''Cont'' data type and its monadic operations, including the class ''MonadCont''.<br />
<br />
;[http://en.wikipedia.org/wiki/Monads_in_functional_programming Article on monads on Wikipedia]<br />
<br />
;[[IO inside]] page<br />
:Explains why I/O in Haskell is implemented with a monad.<br />
<br />
;[http://stefan-klinger.de/files/monadGuide.pdf The Haskell Programmer's Guide to the IO Monad - Don't Panic.] <br />
:By Stefan Klinger. This report scratches the surface of category theory, an abstract branch of algebra, just deep enough to find the monad structure. It seems well written.<br />
<br />
;[https://karczmarczuk.users.greyc.fr/TEACH/Doc/monads.html Systematic Design of Monads]<br />
:By John Hughes and Magnus Carlsson. Many useful monads can be designed in a systematic way, by successively adding facilities to a trivial monad. The capabilities that can be added in this way include state, exceptions, backtracking, and output. Here we give a brief description of the trivial monad, each kind of extension, and sketches of some interesting operations that each monad supports.<br />
<br />
;[[Simple monad examples]]<br />
<br />
<br />
See also: <br />
<br />
* the [[Monad]] HaskellWiki page<br />
* [[Research papers/Monads and arrows]].<br />
* [[Blog articles#Monads |Blog articles]]<br />
* [[Monad tutorials timeline]]<br />
<br />
===Tutorials===<br />
<br />
''The comprehensive list is available at [[Monad tutorials timeline]].''<br />
<br />
;[http://mvanier.livejournal.com/3917.html Mike Vanier's monad tutorial]<br />
:Recommended by David Balaban.<br />
<br />
;[[All About Monads]], [http://www.sampou.org/haskell/a-a-monads/html/index.html モナドのすべて]<br />
:By Jeff Newbern. This tutorial aims to explain the concept of a monad and its application to functional programming in a way that is easy to understand and useful to beginning and intermediate Haskell programmers. Familiarity with the Haskell language is assumed, but no prior experience with monads is required. <br />
<br />
;[[Monads as computation]]<br />
:A tutorial which gives a broad overview to motivate the use of monads as an abstraction in functional programming and describe their basic features. It makes an attempt at showing why they arise naturally from some basic premises about the design of a library.<br />
<br />
;[[Monads as containers]]<br />
:A tutorial describing monads from a rather different perspective: as an abstraction of container-types, rather than an abstraction of types of computation.<br />
<br />
;[http://www.grabmueller.de/martin/www/pub/Transformers.en.html Monad Transformers Step by Step]<br />
:By Martin Grabm&uuml;ller. A small tutorial on using monad transformers. In contrast to others found on the web, it concentrates on using them, not on their implementation.<br />
<br />
;[[What a Monad is not]]<br />
<br />
;[http://noordering.wordpress.com/2009/03/31/how-you-shouldnt-use-monad/ How you should(n’t) use Monad]<br />
<br />
;[http://www-users.mat.uni.torun.pl/~fly/materialy/fp/haskell-doc/Monads.html What the hell are Monads?] <br />
:By Noel Winstanley. A basic introduction to monads, monadic programming and IO. This introduction is presented by means of examples rather than theory, and assumes a little knowledge of Haskell. <br />
<br />
;[http://www.engr.mun.ca/~theo/Misc/haskell_and_monads.htm Monads for the Working Haskell Programmer -- a short tutorial]<br />
:By Theodore Norvell. <br />
<br />
;[http://blog.sigfpe.com/2006/08/you-could-have-invented-monads-and.html You Could Have Invented Monads! (And Maybe You Already Have.)]<br />
:A short tutorial on monads, introduced from a pragmatic approach, with less category theory references <br />
<br />
;[[Meet Bob The Monadic Lover]]<br />
:By Andrea Rossato. A humorous and short introduction to Monads, with code but without any reference to category theory: what monads look like and what they are useful for, from the perspective of a ... lover. (There is also the slightly more serious [[The Monadic Way]] by the same author.)<br />
<br />
;[http://www.haskell.org/pipermail/haskell-cafe/2006-November/019190.html Monstrous Monads]<br />
:Andrew Pimlott's humourous introduction to monads, using the metaphor of "monsters".<br />
<br />
;[http://strabismicgobbledygook.wordpress.com/2010/03/06/a-state-monad-tutorial/ A State Monad Tutorial]<br />
:A detailed tutorial with simple but practical examples.<br />
<br />
;[http://www.reddit.com/r/programming/comments/ox6s/ask_reddit_what_the_hell_are_monads/coxiv Ask Reddit: What the hell are monads? answer by tmoertel] and [http://programming.reddit.com/info/ox6s/comments/coxoh dons].<br />
<br />
;[[The Monadic Way]]<br />
<br />
;[http://www.alpheccar.org/content/60.html Three kind of monads] : sequencing, side effects or containers<br />
<br />
;[http://www.muitovar.com/monad/moncow.html The Greenhorn's Guide to becoming a Monad Cowboy]<br />
:Covers basics, with simple examples, in a ''for dummies'' style. Includes monad transformers and monadic functions. Estimated learning time 2-3 days.<br />
<br />
;[http://ertes.de/articles/monads.html Understanding Haskell Monads]<br />
<br />
;[http://www.reddit.com/r/programming/comments/64th1/monads_in_python_in_production_code_you_can_and/c02u9mb An explanation by 808140]<br />
<br />
==Workshops on advanced functional programming==<br />
<br />
;[http://compilers.iecc.com/comparch/article/95-04-024 Advanced Functional Programming: 1st International Spring School on Advanced Functional Programming Techniques], Bastad, Sweden, May 24 - 30, 1995. Tutorial Text (Lecture Notes in Computer Science) <br />
<br />
;[http://alfa.di.uminho.pt/~afp98/ Advanced Functional Programming: 3rd International School], AFP'98, Braga, Portugal, September 12-19, 1998, Revised Lectures (Lecture Notes in Computer Science) <br />
<br />
;[http://www.staff.science.uu.nl/~jeuri101/afp/afp4/ Advanced Functional Programming: 4th International School], AFP 2002, Oxford, UK, August 19-24, 2002, Revised Lectures (Lecture Notes in Computer Science) <br />
<br />
;[http://www.cs.ut.ee/afp04/ Advanced Functional Programming: 5th International School], AFP 2004, Tartu, Estonia, August 14-21, 2004, Revised Lectures (Lecture Notes in Computer Science) <br />
<br />
More advanced materials available from the [[Conferences|conference proceedings]], and the [[Research papers]] collection.<br />
<br />
<br />
[[Category:Tutorials]]</div>Simonpjhttps://wiki.haskell.org/index.php?title=Haskell_in_education&diff=57397Haskell in education2014-01-15T09:10:13Z<p>Simonpj: /* Haskell as a first language */</p>
<hr />
<div>[[Category:Education]]<br />
This is a collection of material of interest to those teaching or<br />
taking courses that use Haskell. There is also a more general site,<br />
http://www.cs.kun.nl/fple/, devoted to all functional languages. The proceedings of the latest<br />
[http://www.informatik.uni-kiel.de/~mh/publications/reports/fdpe02/ International Workshop on Functional and Declarative Programming in Education (FDPE)] are now available.<br />
Some of the lecture notes and<br />
other course material found in these web pages are excellent<br />
supplements to the available text books.<br />
If you would like to use lecture<br />
notes, assignments, or other material found in these course web pages<br />
please contact the author for permission.<br />
<br />
Most of the entries are years old. When you add your own new<br />
material to this page, please also say when the course was run for the last time.<br />
<br />
The results of a survey of university courses using Haskell in the academic year 2005-2006 can be found [http://www.cs.chalmers.se/~rjmh/Wash/Survey/teaching.htm here]. Also, some news were added during the 2006-2007 academic year.<br />
<br />
== Suitable Course Textbooks ==<br />
<br />
See [[Books#Textbooks]].<br />
<br />
== Haskell as a first language ==<br />
<br />
Here's an [http://chrisdone.com/posts/dijkstra-haskell-java interesting letter from Dijkstra in 2001], explaining why Haskell is an excellent choice for a first year programming language.<br />
<br />
These courses teach Haskell to students with no background in programming.<br />
<br />
<b>Instructor:</b> [http://homepages.inf.ed.ac.uk/wadler/ Philip Wadler] University of Edinburgh<br><br />
<b>Course:</b> [[Informatics 1 - Functional Programming]]<br><br />
<b>Materials:</b> GHCi, Emacs, Thompson: Haskell, the Craft of Functional Programming<br><br />
<b>Web page:</b> http://www.inf.ed.ac.uk/teaching/courses/inf1/fp/ <br><br />
<br />
<br />
<b>Instructor:</b> [mailto:page@ou.edu Rex Page] <br />
University of<br />
Oklahoma<br><br />
<b>Course:</b> Introduction to Computer Programming<br><br />
<b>Student background:</b> High-school mathematics<br><br />
<b>Materials:</b> Projects, Exams, Downloadable textbook: Rex Page, <br />
&quot;Two<br />
Dozen Short Lessons in Haskell&quot;<br><br />
<b>Web page:</b> http://www.cs.ou.edu/~rlpage/fpclassSpring97/<br />
<br />
<b>Comments:</b><br />
<blockquote><br />
These materials arose from a course offered for three consecutive<br />
semesters as<br />
an alternative to our usual first course in programming. Most of the<br />
students<br />
who took the course graduated in the past two years, and many of them<br />
cited it<br />
in the exit interview with the department chair as the most influential<br />
course<br />
in the entire academic career.<br />
<p>All materials for two offerings of the course are available through<br />
the web<br />
page. This includes individual projects, team projects, project<br />
solutions,<br />
exams, supplied software (connected with certain projects), tips for<br />
students<br />
taking the course, FAQs addressing questions that students asked during<br />
the<br />
semester, and a short textbook which served as the primary text in the<br />
course.</p><br />
<p>The first 10 to 11 weeks of the course use Haskell. Students are<br />
required to<br />
write nine programs in Haskell, three of which are team projects that<br />
combine<br />
software developed in individual projects. Different members of a team<br />
are<br />
assigned different individual projects, and the team efforts combine<br />
their<br />
solutions into a working piece of software.</p><br />
<p>In the early part of the course, students use operators like map,<br />
foldr, zip,<br />
and iterate to express computations. Explicit recursion is introduced<br />
after some<br />
experience with these common patterns of computation. Examples and<br />
problems<br />
address non-numeric applications, for the most part. Both interactive<br />
and file<br />
I/O are covered, but general purpose monads are not.</p><br />
<p>The last 5 to 6 weeks of the course use C, and most of the projects<br />
in that<br />
part of the course duplicate the function of earlier pieces of software<br />
that the<br />
students have written in Haskell.</p><br />
</blockquote><br />
<br />
<br />
<b>Instructor:</b> [mailto:Jonathan.Hill@comlab.ox.ac.uk Jonathan Hill]<br />
Oxford University Computing Laboratory<br><br />
<b>Course:</b> Functional Programming for the Integrated Graduate Development Programme in Software Engineering at Oxford University.<br><br />
<b>Student background:</b> Discrete mathematics (the course is a part time MSc for people from industry; most are from IBM or Nortel).<br><br />
<b>Materials:</b> Gofer (an old version, with a stripped down prelude---no parameter classes!); Own course material<br><br />
<b>Web page:</b> http://www.comlab.ox.ac.uk/igdp/text/course06.html<br />
Note: Web pages not accessible. May be ... moved ? <br />
<br />
<br />
<b>Instructor:</b> [mailto:nxg@cs.nott.ac.uk Neil Ghani]<br />
School of Computer Science, University of Nottingham<br><br />
<b>Course:</b> Functional Programming<br><br />
<b>Student background:</b> None<br><br />
<b>Materials:</b> Hugs; Graham Hutton, Programming in Haskell; own lecture slides<br><br />
<b>Web page:</b> http://www.cs.nott.ac.uk/~nxg/G51FUN06/fun.html<br />
<br />
<b>Instructor:</b> [mailto:prins@cs.unc.edu" Jan Prins]<br />
UNC Chapel Hill<br><br />
<b>Course:</b> Introduction to Functional Programming<br><br />
<b>Student background:</b> solid background in high-school science and mathematics<br><br />
<b>Materials:</b> Hugs 1.4 incl. Active Haskell, FRAN and [[Haskore]]; Simon Thompson, "Haskell: The Art of Functional Programming"<br><br />
<b>Web page:</b> http://www.cs.unc.edu/~prins/Classes/15/<br><br />
<b>Comments:</b><br />
<blockquote><br />
(Introductory programming course for CS and math/science majors, typically Freshman and Sophomores. Class size ~60)<br />
<br />
Our undergraduate computing environment is now largely<br />
PCs running Windows NT. We use NTEmacs as the programming<br />
environment with a slightly modified version of Emacs hugs<br />
mode with hugs running as a subprocess. The combined<br />
hugs/NTEmacs/Active Haskell distribution (available through<br />
course home page) is installed on 400+ public Win NT machines<br />
on campus and some unknown number of student-owned Win 95/98<br />
machines.<br />
<br />
This arrangement is new this semester, but so far has been<br />
working well. Keystroke-oriented interactive applications<br />
may be problematic with hugs running in NTEmacs shell mode.<br />
<br />
I'm planning assignments using Fran and Active Haskell and<br />
will try teaching the "brief introduction to imperative<br />
programming" at the end of the class using monads. I would<br />
be interested in talking with anyone who has experience or<br />
suggestions along these lines.<br />
<br />
I took a cue from Paul Hudak and others and have occasional<br />
appearances of MS Agents during lectures to wake students up!<br />
<br />
This is my first time teaching this course, and I would<br />
enjoy talking to others teaching at a similar level. A<br />
cursory search on the web didn't reveal many courses<br />
in this category.<br />
</blockquote><br />
<br />
<br />
<b>Instructor:</b> [mailto:dave@cs.chalmers.se David Sands]<br />
University of Gothenburg & Chalmers University of Technology<br><br />
<b>Course:</b> Programmering för Naturvetare<br><br />
<b>Student background:</b> New students<br><br />
<b>Materials:</b> hugs 1.4; Simon Thompson<br><br />
<b>Web page:</b> http://www.md.chalmers.se/Cs/Grundutb/Kurser/nptah/<br><br />
<b>Comments:</b><br />
<blockquote><br />
This is the first part of a first course in programming. About 16<br />
lectures, each 2x45 mins plus weekly exercise classes and three<br />
assessed programming exercises. Most of my materials are in English.<br />
</blockquote><br />
<br />
<br />
<b>Instructor:</b> [mailto:M.A.Rodrigues@dcs.hull.ac.uk Marcos A Rodrigues]<br />
The University of Hull, Hull, UK<br><br />
<b>Course:</b> Functional and Logic Programming<br><br />
<b>Student background:</b> none<br><br />
<b>Materials:</b> hugs 1.4; Haskell: the Craft of Functional Programming. Thompson S., Addison Wesley, 1996.<br><br />
<br />
<b>Instructor:</b> [mailto:Torsten.Grust@uni-konstanz.de Torsten Grust]<br />
University of Konstanz (Germany)<br> <br />
<b>Course:</b> Deklarative Programmierung (Declarative Programming, in german)<br><br />
<b>Student background:</b> basic math, no programming background required<br><br />
<b>Materials:</b> Hugs 1.4; (~300) slides available from the course web page;<br />
Jeroen Fokker's classroom text: Functional Programming<br />
http://www.cs.uu.nl/~jeroen/courses/fp-eng.ps.gz</a>;<br />
Richard Bird, Phil Wadler: Introduction to Functional Programming; Simon Peyton-Jones: Implementation of Functional Programming Languages<br><br />
<b>Web page:</b> http://www.fmi.uni-konstanz.de/dbis/Courses-old/Courses-ss98/decl-ss98.html<br><br />
<b>Comments:</b><br />
<blockquote><br />
The course is in German only (sorry about that). It additionally<br />
features an introduction to logical programming and Prolog.<br />
</blockquote><br />
<br />
<br />
<b>Instructor:</b> [mailto:richardb@cse.unsw.edu.au Richard Buckland]<br />
University of New South Wales<br><br />
<b>Course:</b> Computing 1A<br><br />
<b>Student background:</b> Mixed, some have no computing<br />
background. This is our cs1 subject.<br><br />
<b>Materials:</b> Hugs 1.4; Simon Thompson<br><br />
<b>Web page:</b> http://www.cse.unsw.edu.au/~cs1011<br><br />
<br />
<br />
<b>Instructor:</b> [mailto:robert@techfak.uni-bielefeld Robert Giegerich], Stefan Posch, University Bielefeld, Germany<br><br />
<b>Course:</b> Introduction to Computer Science<br><br />
<b>Student background:</b> Completed High School (Abitur)<br><br />
<b>Materials:</b> Hugs; Class Notes by Robert Giegerich and Ralf Hinze<br><br />
<b>Comments:</b><br />
<blockquote><br />
Our first semester course<br />
uses Haskell as a vehicle to fundamental aspects of computation:<br />
algorithmics, specification and verification, efficiency analysis,<br />
programming methods. This works wonderfully. We do not require previous<br />
or additional programming experience. Haskell is quickly learned, <br />
to the necessary degreee; we make no attempt to cover the full language.<br />
This is NOT a Haskell course! Haskell allows us to speak about concepts<br />
of computer science WITHOUT a lot of language learning. And Haskell<br />
even helps to keep out detrimental habits from previous programming<br />
experience, as well as motivational problems resulting from the widely<br />
differing previous experiences of our incoming students.<br />
</blockquote><br />
<br />
<br />
<b>Instructor:</b> [mailto:hj@sm.luth.se Håkan Jonsson] Luleå University of Technology, Sweden<br><br />
<b>Course:</b> SMD001, functional programming<br><br />
<b>Student background:</b> <br />
None. This is the very first programming course <br />
our students take.<br><br />
<b>Materials:</b> <br />
Materials: Simon Thompson's Haskell book + 7 laboratory/programming <br />
assignments using Hugs.<br />
<br><br />
<b>Web page:</b>http://www.sm.luth.se/csee/courses/smd/001/ (mostly Swedish)<br> <br />
<br />
<br />
<b>Instructor:</b> [mailto:Clem.Baker-Finch@cs.anu.edu.au Clem Baker-Finch, Australian National University<br><br />
<b>Course:</b>Introduction to Programming and Algorithms<br><br />
<b>Student background:</b> No programming background was<br />
assumed.<br />
<br><br />
<b>Materials:</b> GHC, GHCi, Simon Thompson 1st ed., my own materials. <br />
<br><br />
<b>Web page:</b> http://cs.anu.edu.au/Student/comp1100/<br> <br />
<b>Comments:</b><br />
<blockquote><br />
The first 75% of the course is basic programming concepts using Haskell. The remainder covers the same concepts in Java. This is reinforced - hopefully - by the third assignment (in Java) being the same as the first assignment (in Haskell). The aim is to provide a managed transition to the course which follows in second semester. Another point of possible interest is the use of a simple graphics library, ANUPlot, built on top of the OpenGL binding. See http://code.google.com/p/anuplot/<br />
</blockquote><br />
<br />
<br />
<b>Instructor:</b> [mailto:lyndon@cs.uwa.edu.au Lyndon While] The University of Western Australia<br><br />
<b>Course:</b> Foundations of Computer Science<br><br />
<b>Student background:</b> None<br><br />
<b>Materials:</b> hugs 98; Thompson.<br><br />
<b>Web page:</b> http://undergraduate.cs.uwa.edu.au/courses/230.123<br><br />
<br />
<br />
<b>Instructor:</b> [http://www.cs.us.es/~jalonso José A. Alonso Jiménez] Dept of Computer Science and A.I., University of Seville, Spain<br><br />
<b>Course:</b> Informatics (Inform&aacute;tica, in spanish)<br><br />
<b>Student background:</b> None. This is the very first programming course <br />
our students take.<br><br />
<b>Materials:</b> GHCi, Emacs, Graham Hutton: &quot;Programming in Haskell&quot;, Slides, Exercises, Exams <br><br />
<b>Web page:</b> http://www.cs.us.es/~jalonso/cursos/i1m (in spanish)<br><br />
<b>First run:</b> 2009–2010<br><br />
<b>Last run:</b> 2012–2013<br />
<br />
----<br />
<br />
== Haskell as a second language ==<br />
<br />
These courses teach Haskell to students that have already learned<br />
another language.<br />
<br />
<b>Instructor:</b> [mailto:page@ou.edu Rex Page]<br />
University of Oklahoma<br><br />
<b>Course:</b> Discrete Mathematics<br><br />
<b>Student background:</b> High-school mathematics, introductory programming<br />
course (any language)<br><br />
<b>Materials:</b> Lecture notes, Projects, Exams, Solutions, Proof checking<br />
tools, etc.; text: Hall and O'Donnell, &quot;Discrete Mathematics with a<br />
Computer&quot;<br><br />
<br />
<b>Web page:</b> http://www.cs.ou.edu/~beseme/<br><br />
<b>Comments:</b><br />
<blockquote><br />
Lecture notes comprise over 350 animated slides (all both PowerPoint and<br />
PDF<br />
formats). About two-thirds of the material centers around mathematical logic.<br />
After the introduction of predicates, all of the examples in the logic<br />
portion<br />
of the course involve reasoning about properties of software, most of which is<br />
expressed in Haskell (a few are conventional looping functions).<br />
<p>Software examples include sum, sequence concatenation, logical operations on<br />
sequences, the Russian peasant algorithm, insertion and lookup in AVL <br />
trees, and<br />
other computations. Most of the properties verified relate to aspects of <br />
program<br />
correctness, but resource utilization properties are also verified in <br />
some<br />
cases. Several semesters worth of exams (finals and exams given during <br />
the term)<br />
are provided. The slides have matured through several offerings of the course.</p><br />
<p>The remaining third of the course discusses other standard topics<br />
in discrete<br />
mathematics, such as sets, functions, relations, trees, and counting.<br />
The web<br />
page provides access to a preview of the material. Exams and solutions are<br />
protected by a login procedure (to increase the comfort level of<br />
instructors<br />
wishing to use them in courses). The web page provides a link through<br />
which<br />
instructors may gain access to the full website.</p><br />
</blockquote><br />
<br />
<br />
<b>Instructor:</b> [mailto:labra@lsi.uniovi.es Jose Emilio Labra Gayo],<br />
Dept. of Computer Science (EUITIO) University of Oviedo<br><br />
<b>Course:</b> Logic and Functional Programming<br><br />
<b>Student background:</b> The course is oriented towards third year undergraduate students in computer science. Usually, the students have been<br />
introduced to imperative languages like Pascal and Object <br />
Oriented Languages like C++<br><br />
<b>Materials:</b> Hugs; R. Bird "Introd. to FP using Haskell" (2nd Ed), J. E. Labra Gayo. "Introduction to the Haskell Language" (in spanish).<br><br />
<b>Web page:</b> http://lsi.uniovi.es/~labra/plf.html (in spanish).<br />
My FP page: http://lsi.uniovi.es/~labra/FuncProg.html<br><br />
<br />
<br />
<b>Instructor:</b> [mailto:fruehr@willamette.edu Fritz Ruehr]<br />
Willamette University, Salem, Oregon, USA (a small Liberal Arts College, about 1 hour from Portland & OGI)<br><br />
<b>Course:</b> CS 451 Topics in Computer Science: Functional Programming<br><br />
<b>Student background:</b> Data structures (I may also have required discrete math)<br><br />
<b>Materials:</b> Hugs 1.4 beta (I also taught Scheme); Haskell: The Craft of Functional Programming by Simon Thompson (I also used my own on-line lecture notes and labs and Kent Dybvig's text on Scheme)<br><br />
<b>Web page:</b> http://www.willamette.edu/~fruehr/451/<br><br />
<b>Comments:</b><br />
<blockquote><br />
The notes and labs I have on-line are in pretty rough form: many slide <br />
points are just one-line topical stubs I used as reminders in lecture.<br />
Many of the on-line materials are not linked into the (out of date)<br />
home page.<br />
<br />
I hope to have the course approved for next Fall as a regular offering<br />
(i.e., not as a "special topic") and should have more extensive<br />
on-line materials up by then.<br />
<br />
Teaching "bi-lingually" in Haskell and Scheme seemed like a good idea<br />
at the time, but next time around I will use Haskell as the main vehicle,<br />
perhaps taking some time near the end of the course to highlight some<br />
other languages (Scheme, ML, Clean).<br />
<br />
Some of my students used Conal Elliot's Fran and Paul Hudak's Haskore<br />
and liked them a lot; I was nice to have some significantly-sized<br />
applications that seemed more practical and fun to show off at the end<br />
of the course (I should have demonstrated these things at the beginning<br />
of the course to help with motivation). Next time around I would like to<br />
have a "beginner's prelude" or similar available to avoid problems with<br />
classes in type inference, Int vs. Integer, etc. These problems were a<br />
constant annoyance during lectures.<br />
</blockquote><br />
<br />
<br />
<b>Instructor:</b> [mailto:J.Hamer@cs.auckland.ac.nz John Hamer],<br />
University of Auckland<br><br />
<b>Course:</b> Logic and Functional Programming<br><br />
<b>Student background:</b> Year 2 programming + some discrete maths<br><br />
<b>Materials:</b> Hugs 98, Haskell School of Expression, Page "Two Dozen Short Lessons in Haskell",<br><br />
<b>Web page:</b> http://www.cs.auckland.ac.nz/compsci360fc<br><br />
<br />
<br />
<b>Instructor:</b> [mailto:lengauer@fmi.uni-passau.de Chris Lengauer]<br />
University of Passau<br><br />
<b>Course:</b> Functional Programming<br><br />
<b>Student background:</b> two years of CS study<br><br />
<b>Materials:</b> hugs; Richard Bird's new text (PHI)<br><br />
<b>Web page:</b> not reachable from outside Passau<br><br />
<br />
<br />
<b>Instructor:</b> [mailto:cunningham@cs.olemiss.edu Conrad Cunningham]<br />
University of Mississippi<br><br />
<b>Course:</b> Functional Programming<br><br />
<b>Student background:</b> official -- senior or graduate standing; actual -- introductory programming, data structures, and discrete math<br><br />
<b>Materials:</b> Hugs on Unix and MS Windows systems;<br />
Mostly use the instructor's own set of lecture notes. Also Simon Thompson's HASKELL: THE CRAFT OF FUNCTIONAL PROGRAMMING. Previously used the Bird and Wadler textbook<br><br />
<b>Web page:</b> http://www.cs.olemiss.edu/~hcc/csci555/<br><br />
<b>Comments:</b><br />
<blockquote><br />
Although I am not a researcher in FP, I enjoy teaching the FP course.<br />
Most of the students take to the course after a few weeks. Hugs works<br />
reasonably well, but, of course, more pedagogically oriented error messages<br />
and other support tools would be helpful.<br />
</blockquote><br />
<br />
<br />
<b>Instructor:</b> [mailto:leavens@cs.iastate.edu Gary T. Leavens],<br />
Iowa State University<br><br />
<b>Course:</b> Programming Languages 1<br><br />
<b>Student background:</b> undergraduate course in compilers or programming languaages<br><br />
<b>Materials:</b> Hugs 1.4; Thompson's Haskell: The Craft of Programming<br><br />
<b>Web page:</b> http://www.cs.iastate.edu/~leavens/ComS541.html<br><br />
<b>Comments:</b><br />
<blockquote><br />
Be sure to tell your students how to debug programs.<br />
</blockquote><br />
<br />
<br />
<b>Instructor:</b> [mailto:jtod@dcs.gla.ac.uk John O'Donnell]<br />
University of Glasgow<br><br />
<b>Course:</b> Functional Programming<br><br />
<b>Student background:</b> Programming (in Ada), Algorithmic Foundations<br><br />
<b>Materials:</b> Hugs; Simon Thompson's book on Haskell<br><br />
<b>Web page:</b> http://www.dcs.gla.ac.uk/courses/teaching/level2/modules/#FP2<br><br />
<br />
<b>Instructor:</b> [mailto:chitil@informatik.rwth-aachen.de Olaf Chitil],<br />
RWTH Aachen, Germany<br><br />
<b>Course:</b> Functional Programming in Haskell<br><br />
<b>Student background:</b> basic programming skills (not necessarily in a<br />
functional language)<br><br />
<b>Materials:</b> Hugs 1.4; Hugs user manual, slide copies;<br />
additionally the `Gentle Introduction to Haskell', probably Bird's `Introduction<br />
to Functional Programming using Haskell' in the future.<br><br />
<b>Web page:</b> http://www-i2.informatik.rwth-aachen.de/Praktikum/SWP/ (in German)<br><br />
<b>Comments:</b><br />
<blockquote><br />
The course starts with 4 full time days of learning Haskell. During the semester<br />
the students (in groups of 2 students) have to implement a compiler and an<br />
abstract machine for a simple imperative language. They are given parts of the<br />
system and a manual on how to do the remaining parts (they have no prior<br />
knowledge on compiler construction).<br />
The most difficult construct for students to understand is the monad. I<br />
introduce IO without mentioning monads. Later I explain how to build a simple<br />
exception handling system based on the type `Maybe a' / `Error a'. Only<br />
subsequently I give the general definition of monads and present the list monad<br />
and a simple state monad. However, I fear that just to understand the bind<br />
operator `>>=' requires people to be quite comfortable with higher-order<br />
functions.<br />
</blockquote><br />
<br />
<br />
<b>Instructor:</b> [http://web.comlab.ox.ac.uk/oucl/people/richard.bird.html Richard Bird], Oxford Brookes University<br><br />
<b>Course:</b> Functional Programming<br><br />
<b>Student background:</b> Elementary structured programming<br><br />
<b>Web page:</b> http://web.comlab.ox.ac.uk/oucl/courses/topics00-01/fp/<br><br />
<br />
<br />
<b>Instructor:</b> [mailto:paul.hudak@yale.edu Paul Hudak],<br />
Yale University, Dept of Computer Science<br><br />
<b>Course:</b> Functional Programming<br><br />
<b>Student background:</b> at least one programming course<br><br />
<b>Materials:</b> Hugs; my own textbook, which is under preparation<br><br />
<b>Web page:</b> none<br><br />
<br />
<br />
<b>Instructor:</b> [mailto:abf@cs.ucc.ie Alex Ferguson]<br />
University College Cork<br><br />
<b>Course:</b> Functional and Logic Programming<br><br />
<b>Student background:</b> Final year undergraduate<br />
<br><br />
<b>Materials:</b> Final year undergraduate<br />
Materials: Hugs 98; ghc; Simon Thompson, "Haskell: The Craft of<br />
Functional Programming" (2nd ed.)<br />
<br><br />
<b>Web page:</b> http://yeats.ucc.ie/~abf/CS4001/<br> <br />
<b>Comments:</b><br />
<blockquote><br />
This is the declarative programming option for 4th year<br />
undergrads, who have Java as a first programming language, and some<br />
knowledge of C and C++. The current final year have had some exposure<br />
to Haskell in first year, though this is no longer the case for our<br />
current intake.<br />
</blockquote><br />
<br />
<br />
<b>Instructor:</b> [mailto:lky@nada.kth.se Leif Kusoffsky],<br />
Royal Institute of Technology, Stockholm<br><br />
<b>Course:</b> Functional Programming 2D1370<br><br />
<b>Student background:</b> The course is oriented towards third year<br />
undergraduate students in computer science. The students<br />
have been introduced to imperative languages like<br />
C and Object Oriented Languages like Java<br />
<br><br />
<b>Materials:</b> Hugs; Hudak : The Haskell School of Expression<br />
<br><br />
<br />
<br />
<b>Instructor:</b> Jeremy Bobbio -- INSIA<br><br />
<b>Course:</b> Functional and Logic Programming<br><br />
<b>Student background:</b> One year CS<br />
<br><br />
<b>Materials:</b> <br />
Hugs, GHC, Paul Hudak's Haskell School of Education<br />
<br><br />
<b>Web page:</b> http://etudiants.insia.org/~jbobbio/pafp/ (french)<br> <br />
<br />
<br />
<b>Instructor:</b> [mailto:antkaij@mit.jyu.fi Antti-Juhani Kaijanaho]<br />
University of Jyväskylä<br><br />
<b>Course:</b> Functional Programming 1 & 2<br><br />
<b>Student background:</b> third-year undergraduate and up<br />
<br><br />
<b>Materials:</b><br />
GHC, Gtk2HS<br />
<br><br />
<b>Web page:</b> [http://www.mit.jyu.fi/antkaij/opetus/fo/2005-2006/index.en.html]<br />
<br><br />
<b>Last run:</b> 2005&ndash;2006<br />
<br><br />
<!--<b>Comments:</b><br />
<blockquote><br />
(I'll write this later)<br />
</blockquote>--><br />
<br />
<b>Instructor:</b> [mailto:djd@comp.leeds.ac.uk David Duke]<br />
University of Leeds, School of Computing<br><br />
<b>Course:</b> Functional Programming<br><br />
<b>Student background:</b> Second and third year undergraduate<br />
<br><br />
<b>Materials:</b> ghc; Graham Hutton "Programming in Haskell"<br />
<br><br />
<b>Web page:</b> www.comp.leeds.ac.uk/se23/<br> <br />
<b>Comments:</b><br />
<blockquote><br />
This is an optional course that students currently can take in <br />
second or third year (from 2008/9 it will be third-years only).<br />
Students will have previously used Python and Java.<br />
Although the emphasis is on learning to solve problems within<br />
the functional paradigm, and how to develop solutions within<br />
Haskell, I also like to show students what is "under the<br />
bonnet" and conclude the module with an introduction to<br />
implementation issues, using material derived from<br />
"Implementing Functional Languages" by Simon Peyton Jones and <br />
David Lester. <br />
</blockquote><br />
<br />
<b>Instructor:</b> [mailto:popavdan@yahoo.com Popa V. Dan]<br />
University of Bacau, Romania <br><br />
<b>Course:</b> "Limbaje formale si automate" (Formal languages and automata) <br><br />
<b>Student background:</b> second-year undergraduate <br />
<br><br />
<b>Materials:</b> Hugs 98 (2002 revised version) included in Mandriva (Formely Mandrake) 10.0 Linux Distribution<br />
<br><br />
<b>Web page:</b> Not yet. Try the page of the "ro" community on www.haskell.org<br />
<br> [http://www.haskell.org/haskellwiki/Ro/Haskell Ro/Haskell webpage is here] <br><br />
<b>First run:</b> 2006&ndash;2007<br />
<br><br />
<br />
Haskell is used as an implementation languages in student's laboratories.<br />
The ideea was to provide a language powerfull enough to be able to express <br />
how to build a parser starting from a grammmar. The students are able<br />
to build small (monadic) interpreters for "while-languages" using a <br />
recommanded monad and a recommanded back-end. The labs are focusing on the <br />
grammar of the languages, on the modular (monadic) parsing as a tool for <br />
verifying and processing inputs which are not validable by finite state <br />
automata but by context free grammmars. Adaptability of the language, <br />
especially obtained manipulating and improving syntax is also a target.<br />
<br />
Support (concerning Haskell): "O introducere in Haskell prin exemple" by<br />
Dan Popa, published in january 31,2007 by <br />
[http://www.edusoft.ro Edusoft](in romanian) Contact the author if needed .<br />
<br />
Other recommanded books: "Gentle Introd to Haskell 98" and YAHT <br />
Recomanded papers: All about monadic parsing. <br />
Special message for Graham Hutton, Erik Meijer and P. Wadler and all <br />
other authors with similar interests from the Haskell <br />
community:<br />
<br />
Thank you very much for your papers concerning Monadic parsing and <br />
interpreters ! <br><br />
<br />
<br />
'''List of Instructors:''' Involved people [http://www.pdep.com.ar/Home/quines-somos [1]] National and Technological University, Buenos Aires, Argentina (Universidad Tecnológica Nacional - Facultad Regional Buenos Aires)<br><br />
'''Course:''' Programming Paradigms <br><br />
'''Student background:''' This is a second-year undergraduate course. Students have already been introduced to basic structured programming concepts. <br><br />
'''Materials:''' Pharo Smalltalk; LOOP [http://www.esug.org/wiki/pier/Conferences/2011/InnovationTechnologyAwards [2]] , SWI-Prolog, Hugs, GHC, "Learn You a Haskell For a Great Good" (Spanish Version), Lecture Notes, Exams. <br><br />
'''Web page:''' You can find our homepage in [http://www.pdep.com.ar here] (Only Spanish Version).<br />
<br />
Students are being introduced to three main programming paradigms: <br><br />
<br />
• Object Oriented Programming <br><br />
• Logical Programming <br><br />
• Functional Programming <br><br />
<br />
----<br />
<br />
== Comparative programming languages ==<br />
<br />
These courses teach general programming language principles, with<br />
Haskell as an example of a functional language.<br />
<br />
<b>Instructor: </b> Ruediger Marcus Flaig, University of Heidelberg (Germany)<br />
<br><br />
<b>Course:</b> An introduction to programming in bioinformatics <br><br />
<b>Student background:</b> different, but generally low<br><br />
<b>Materials:</b> Hugs-98 and lots of other stuff<br />
<br><br />
<b>Web page:</b> http://www.sanctacaris.net/rc.html<br> <br />
<b>Comments:</b><br />
<blockquote><br />
This course is designed to introduce life science students,<br />
that is to say, going-to-be biologists, physicians, biotechnologists<br />
and maybe others, to solving real-life problems (such as DNA sequence<br />
handling and analysis). Emphasis will be on paradigms (imperative /<br />
OO, functional, declarative). Although -- in order not to frighten<br />
people -- the official announcement mentions only Python, Haskell will<br />
be presented as THE purely functional language, and all solutions may<br />
be presented in either Python, Haskell or Java. I am very curious<br />
about the feedback I'll get, and maybe next term we shall focus more<br />
on Haskell. What I'd really need, though, is some life science related<br />
package for Haskell, such as BIOPYTHON and BIORUBY. <br />
</blockquote><br />
<br />
<br />
<b>Instructor:</b> [mailto:ham@cs.utexas.edu Hamilton Richards],<br />
University of Texas (Austin)<br><br />
<b>Course:</b> Programming Languages (taught in 2005)<br><br />
<b>Student background:</b> <br><br />
<b>Materials:</b> Hugs 1.4; Sethi, Davie.<br><br />
<b>Web page:</b> http://www.cs.utexas.edu/users/ham/UTCS/CS345/<br><br />
<b>Comments:</b><br />
<blockquote><br />
I'm using Haskell in a programming-languages course, but it's distributed<br />
somewhat piecemeal through the course. Probably adds up to something like<br />
3-4 weeks (out of 15).<br />
</blockquote><br />
<br />
<br />
<b>Instructor:</b> [http://www.cs.waikato.ac.nz/~marku Mark Utting]<br />
University of Waikato (New Zealand)<br />
<b>Course:</b> Programming Languages<br><br />
<b>Student background:</b> Two years of C++ and 1 year of Haskell<br><br />
<b>Materials:</b> Textbook "Programming Languages", Louden.<br />
<b>Web page:</b> http://www.cs.waikato.ac.nz/~marku/313<br><br />
<b>Comments:</b><br />
<blockquote><br />
The course covers at least two languages in each of the<br />
main paradigms (object-oriented, functional and logic programming),<br />
plus history, semantics and implementation issues.<br />
The Haskell section is about 2 weeks long and usually focusses on <br />
programming with higher-order functions and how that enables the<br />
language to be extended in application-specific ways<br />
(parser combinators, html-generation combinators etc.)<br />
</blockquote><br />
<br />
<b>Instructor:</b> [mailto:zeeshan@apiit.edu.pk M Zeeshan Ali Ansari],<br />
Asia Pacific Institute of Information Technology (Pakistan)<br><br />
<b>Course:</b> Advanced Programming Language Concepts<br><br />
<b>Student background:</b> Students having studied and worked on Imperative Programming Languages <br><br />
<b>Materials:</b> The Craft of Haskell, A Gentle Introduction to Haskell, Yet Another Haskell Tutorial.<br><br />
<b>Web page:</b> http://www.apiit.edu.pk<br><br />
<b>Comments:</b><br />
<blockquote><br />
This course compares and contrasts various programming language paradigms including Functional Programming. Out of 13 week course 5 to 6 of them are dedicated towards Haskell. The material is basically written in a way that enables imperative language programmers to understand the concepts and power of functional programming <br />
<br />
http://www.haskell.org/sitewiki/images/3/3d/Functional_Programming_Tutorial_By_Zeeshan_Ali_Ansari.doc<br />
<br />
<br />
</blockquote><br />
<br />
<b>Instructor:</b> John C. Mitchell,<br />
Stanford University<br><br />
<b>Course:</b> Programming Languages<br><br />
<b>Student background:</b> Some experience with Lisp/C/object-oriented languages.<br><br />
<b>Materials:</b> Concepts in Programming Languages (new Haskell chapters written with Kathleen Fisher)<br><br />
<b>Web page:</b> http://cs242.stanford.edu<br><br />
<b>Comments:</b><br />
<blockquote><br />
Central concepts in modern programming languages, impact on software development, language design trade-offs, and implementation considerations. Functional, imperative, and object-oriented paradigms. Formal semantic methods and program analysis. Modern type systems, higher order functions and closures, exceptions and continuations. Modularity, object-oriented languages, and concurrency. Runtime support for language features, interoperability, and security issues. <br />
</blockquote><br />
<br />
----<br />
<br />
== Advanced functional programming using Haskell ==<br />
<br />
These courses deal with the advanced issues such as semantics, type<br />
systems, or compilers. Includes a other advanced courses taught using<br />
Haskell. <br />
<br />
<b>Instructor:</b> [mailto:gmh@cs.nott.ac.uk Graham Hutton]<br />
School of Computer Science, University of Nottingham<br><br />
<b>Course:</b> Advanced Functional Programming<br><br />
<b>Student background:</b> At least one year of CS, including a course in Haskell<br><br />
<b>Materials:</b> Hugs; GHC; Graham Hutton, Programming in Haskell; own course material<br><br />
<b>Web page:</b> http://www.cs.nott.ac.uk/~gmh/afp.html<br />
<br />
<b>Instructor:</b> [mailto:rjmh@cs.chalmers.se John Hughes]<br />
Chalmers University, Gothenburg<br><br />
<b>Course:</b> Advanced Functional Programming<br><br />
<b>Student background:</b> General CS maturity; from this year most students have already used Haskell in introductory courses.<br><br />
<b>Materials:</b> Mainly hbc.; Papers (see web page)<br><br />
<b>Web page:</b> http://www.cs.chalmers.se/~rjmh/AFP<br><br />
<b>Comments:</b><br />
<blockquote><br />
The goal is to teach students how to solve substantial problems in a<br />
functional language --- `functional programming in anger', one might say. The<br />
emphasis is on design and use of suitable combinator libraries to simplify<br />
applications. Material covered includes monad design, use of CPS style,<br />
libraries for parsing, pretty-printing, and GUIs (presently fudgets). <br />
<br />
The course is taught in a `problem based' manner: lectures are few, while<br />
students solve three substantial programming problems during the term, with<br />
plenty of backup via group meetings. I adopted this teaching form three years<br />
ago, and it has led students to develop far better practical skills than most<br />
obtained from my earlier `lectures and exercises' courses, and I believe to<br />
use Haskell much more after the course's end.<br />
<br />
This course is optional in the third or fourth year, and is taken by a<br />
small-to-medium sized group of students.<br />
</blockquote><br />
<br />
<br />
<b>Instructor:</b> [mailto:Olof.Johanssson@cs.umu.se Olof Johansson], Umeå Univesity, Department of Computing Science<br><br />
<b>Course:</b> Programming language semantics<br><br />
<b>Student background:</b> two terms of computer science studies and specificaly a course Programming language concepts<br><br />
<b>Materials:</b> Hugs and some HBC and GHC; Watt, Programming language, Syntax and Semantics<br><br />
<b>Web page:</b> http://www.cs.umu.se/local/kurser/TDBC05 (Only in swedish)<br> <br />
<br />
<br />
<b>Instructor:</b> [mailto:lyndon@cs.uwa.edu.au Lyndon While]<br />
The University of Western Australia<br><br />
<b>Course:</b> Functional Programming<br><br />
<b>Student background:</b> OOP, plus most of them have used Haskell previously<br><br />
<b>Materials:</b> hugs 98; none of the recent books really fit<br><br />
<b>Web page:</b> http://undergraduate.cs.uwa.edu.au/courses/230.301<br><br />
<b>Instructor:</b> [mailto:F.A.Rabhi@dcs.hull.ac.uk Fethi Rabhi],<br />
University of Hull (UK)<br><br />
<b>Course:</b> AI Problem Solving Techniques (using Haskell and Prolog)<br><br />
<b>Student background:</b> Haskell and Prolog programming<br><br />
<b>Materials:</b> HUGS; Thompson'96, own notes (soon to be published as a book).<br><br />
<b>Web page:</b> none<br><br />
<b>Comments:</b><br />
<blockquote><br />
It is very hard to justify learning Haskell unless it can be<br />
demonstrated in very practical situations (hence the provision<br />
of the above course).<br />
</blockquote><br />
<br />
<br />
<b>Instructor:</b> [mailto:karczma@info.unicaen.fr Jerzy Karczmarczuk]<br />
University of Caen, Caen (France)<br> No links in the fr-Haskell page. Why not ?<br />
<b>Course:</b> Compilation<br><br />
<b>Student background:</b> General CS knowledge; students (should...) know Scheme and imperative languages, also some theory of languages and automata.<br><br />
<b>Materials:</b> <br />
Hugs, GHC, now also GHCi, and their documentation. Handouts: (still a little incomplete)<br />
Impossible to find the foolowing matterials.Files can not be found. <br />
* http://users.info.unicaen.fr/~karczma/matrs/Maitcomp/compilation_a.pdf<br />
* http://users.info.unicaen.fr/~karczma/matrs/Maitcomp/compilation_b.pdf<br />
* http://users.info.unicaen.fr/~karczma/matrs/Maitcomp/compilation_c.pdf<br />
<b>Comments:</b><br />
<blockquote><br />
This is a compulsory semestrial course in fourth year. Weekly: 1.5h<br />
course, 2.5H practice.<br />
One, but comprehensive assignment, taking 2 months or more.<br />
askell is our main coding tool. A little time is devoted by necessity<br />
to the language<br />
itself, but also from the perspective: "how would you compile such a<br />
language".<br />
"Standard stuff", such as parsing combinators, etc.is covered, but we<br />
don't begin with that.<br />
We start with the construction of small interpreters: from recursive<br />
Lisp-style to postfix,<br />
(Forth/PostScript style) constructing this last by partial evaluation<br />
(intuitively).<br />
We introduce control structures as lazy functions, operation<br />
sequencing through continuations,<br />
monads not only for parsing, but also for exceptions and<br />
non-determinism.<br />
We discuss (simply) the type inference. The code generator assembles a<br />
linear code by lazy<br />
concatenation of chunks which makes it trivial to deal with loops and<br />
cross-referencing<br />
fragments. Algorithms of garbage collection are presented (not<br />
implemented, though...) in<br />
a purely functional style.<br />
<br />
Students' opinion: "Frightening at first. Learning curve steep, but<br />
much less time spent on debugging, coding proficiency comes fast. Good for<br />
understanding what the compilation is about, but difficult to make a<br />
complete running program with all the I/O, etc.<br />
</blockquote><br />
<br />
<br />
<b>Instructor:</b> [mailto:jeffm@cse.uconn.edu Jeffrey A. Meunier], University of Connecticut<br><br />
<b>Course:</b> CSE240 Intermediate Computer Systems<br><br />
<b>Student background:</b> computer/microprocessor organization<br />
<br><br />
<b>Materials:</b> Hugs (Feb 2001); Bird ``Introduction to Functional<br />
Programming''; Furber ``ARM System-on-Chip Architecture''<br />
<br><br />
<b>Web page:</b> http://www.engr.uconn.edu/~jeffm/Classes/CSE240-Spring-2001/index.html<br> <br />
<b>Comments:</b><br />
<blockquote><br />
This is a course in the low level programming of microprocessor systems.<br />
The course will focus on the development of an emulator (virtual<br />
machine, or VM) for a small computer system based on a modern RISC<br />
microprocessor (the ARM CPU) using a high level programming language<br />
(Haskell), and assembly language programming of the VM. Development of<br />
the VM will occur in stages, starting with the simple direct-execution<br />
(stream-based) model, gradually moving to a more realistic memory-mapped<br />
model, including exception handlers, concurrent processes, and<br />
asynchronous external devices.<br />
</blockquote><br />
<br />
<b>Instructor:</b> Gabriele Keller<br />
The University of New South Wales<br><br />
<b>Course:</b> Concepts of Programming Languages<br><br />
<b>Student background:</b> Most of them have used Haskell in first year<br><br />
<b>Materials:</b> GHC, TaPL and `Programming Languages: Theory and Practice', papers<br><br />
<b>Web page:</b> http://www.cse.unsw.edu.au/~cs3161<br><br />
<b>Last run:</b> 2006<br><br />
<b>Comments:</b><br />
<blockquote><br />
Expose students to a theory of programming languages based on type<br />
theory and operational semantics as a mathematically sound framework<br />
which allows us to investigate the properties of a large number of<br />
programming language features, including:<br />
<br />
* on semantics of different programming languages and programming paradigms: imperative, object oriented, and declarative.<br />
* theoretical foundations of programming languages: syntax, operatational, axiomatic and denotational semantics.<br />
* implementation aspects of central language features, such as dynamic and strong typing, polymorphism, overloading and automatic memory management<br />
<br />
Assignments are in GHC/Haskell, and in the past have included implementing a<br />
mini-Haskell type checker, type inference and interpreter.<br />
</blockquote><br />
<br />
<b>Instructor:</b> Manuel Chakravarty<br />
The University of New South Wales<br><br />
<b>Course:</b> Advanced Functional Programming<br><br />
<b>Student background:</b> Most of them have used Haskell in first year<br><br />
<b>Materials:</b> GHC, papers (see the website)<br><br />
<b>Web page:</b> http://www.cse.unsw.edu.au/~cs4132<br><br />
<b>Last run:</b>2004<br><br />
<b>Comments:</b><br />
<blockquote><br />
To provide students with an understanding of the theory and practice of<br />
the design, use, and implementation of functional programming languages,<br />
such as Haskell<br />
<br />
This includes selected topics from the following areas:<br />
<br />
* Foundations: lambda calculus, semantics, and type systems.<br />
* Design: side-effects, exceptions, concurrency, and parallelism.<br />
* Implementation: abstract machines, program transformation, and memory management. <br />
* Programming techniques: combinator libraries, monads, generic programming, and meta programming.<br />
* Applications: domain specific languages, graphics, web programming, reactive systems, and scientific programming.<br />
</blockquote><br />
<br />
[[Category:Community]]</div>Simonpjhttps://wiki.haskell.org/index.php?title=GHC/As_a_library&diff=56643GHC/As a library2013-08-22T12:20:51Z<p>Simonpj: /* Links */</p>
<hr />
<div>''For instructions on the GHC API with GHC 6.8 or older please refer to [[GHC/As a library (up to 6.8)]]''<br />
<br />
__TOC__<br />
<br />
== Introduction ==<br />
<br />
GHC's functionality can be useful for more things than just compiling Haskell programs. Important use cases are programs that analyse (and perhaps transform) Haskell code. Others include loading Haskell code dynamically in a GHCi-like manner. For this reason, a lot of GHC's features can be accessed by programs which import the <tt>ghc</tt> package.<br />
<br />
The instructions on this page concern the API of GHC 6.10.1 and above. Please note that the GHC API is still in flux and may change quite significantly between major releases while we (the GHC team) provide new features or simplify certain aspects.<br />
<br />
<br />
== Getting Started ==<br />
<br />
To use the GHC API you need GHC 6.10.1 or above and import the <tt>ghc</tt> package.<br />
<pre><br />
ghc -package ghc my_program.hs<br />
</pre><br />
In most cases you probably also want to use the [http://hackage.haskell.org/cgi-bin/hackage-scripts/package/ghc-paths ghc-paths package].<br />
<br />
Most of the common functionality is provided by the <tt>GHC</tt> module, but occasionally you may have to import other modules. See the GHC's [http://www.haskell.org/ghc/docs/latest/html/libraries/ghc/index.html haddock documentation] for a list of these modules. One good entry point into the docs is [http://www.haskell.org/ghc/docs/latest/html/libraries/ghc/GHC.html GHC].<br />
== A Simple Example ==<br />
<br />
The following little program essentially does what <tt>ghc --make</tt> does.<br />
<br />
<haskell><br />
{-# LANGUAGE CPP #-}<br />
import GHC<br />
import GHC.Paths ( libdir )<br />
import DynFlags<br />
<br />
main = <br />
#if __GLASGOW_HASKELL__ > 704<br />
defaultErrorHandler defaultFatalMessager defaultFlushOut $ do<br />
#else<br />
defaultErrorHandler defaultLogAction $ do<br />
#endif<br />
runGhc (Just libdir) $ do<br />
dflags <- getSessionDynFlags<br />
setSessionDynFlags dflags<br />
target <- guessTarget "test_main.hs" Nothing<br />
setTargets [target]<br />
load LoadAllTargets<br />
</haskell><br />
<br />
The outermost function, <tt>defaultErrorHandler</tt>, sets up proper exception handlers and prints an error message and exits with exit code 1 if it encounters one of these exceptions.<br />
<br />
Most of GHC's high-level API requires access to a current session. Therefore, these functions require to be called inside a monad that is an instance of the <tt>GhcMonad</tt> typeclass. Two default implementations of this typeclass are <tt>Ghc</tt> and <tt>GhcT</tt>. In the above example we used the <tt>Ghc</tt> monad since we don't need to track any extra state.<br />
<br />
The argument to <tt>runGhc</tt> is a bit tricky. GHC needs this to find its libraries, so the argument must refer to the directory that is printed by <tt>ghc --print-libdir</tt> for the ''same'' version of GHC that the program is being compiled with. Above we therefore use the <tt>ghc-paths</tt> package which provides this for us.<br />
<br />
== Another example ==<br />
<br />
Here we demonstrate calling [http://www.haskell.org/ghc/docs/latest/html/libraries/ghc/GHC.html#v:parseModule parseModule], [http://www.haskell.org/ghc/docs/latest/html/libraries/ghc/GHC.html#v:typecheckModule typecheckModule], [http://www.haskell.org/ghc/docs/latest/html/libraries/ghc/GHC.html#v:desugarModule desugarModule], [http://www.haskell.org/ghc/docs/latest/html/libraries/ghc/GHC.html#v:getNamesInScope getNamesInScope], and [http://www.haskell.org/ghc/docs/latest/html/libraries/ghc/GHC.html#v:getModuleGraph getModuleGraph]. This works for haskell-platform, ghc-7.0.3 to ghc-7.6.x. It also demonstrates how to enable some extensions.<br />
<br />
<haskell><br />
--A.hs<br />
--invoke: ghci -package ghc A.hs<br />
<br />
{-# LANGUAGE CPP #-}<br />
import GHC<br />
import Outputable<br />
<br />
import GHC.Paths ( libdir )<br />
--GHC.Paths is available via cabal install ghc-paths<br />
<br />
import DynFlags<br />
targetFile = "B.hs"<br />
<br />
main = do<br />
res <- example<br />
#if __GLASGOW_HASKELL__ > 704<br />
putStrLn $ showSDoc tracingDynFlags ( ppr res )<br />
#else<br />
putStrLn $ showSDoc ( ppr res )<br />
#endif<br />
<br />
example = <br />
#if __GLASGOW_HASKELL__ > 704<br />
defaultErrorHandler defaultFatalMessager defaultFlushOut $ do<br />
#else<br />
defaultErrorHandler defaultLogAction $ do<br />
#endif<br />
runGhc (Just libdir) $ do<br />
dflags <- getSessionDynFlags<br />
let dflags' = foldl xopt_set dflags<br />
[Opt_Cpp, Opt_ImplicitPrelude, Opt_MagicHash]<br />
setSessionDynFlags dflags'<br />
target <- guessTarget targetFile Nothing<br />
setTargets [target]<br />
load LoadAllTargets<br />
modSum <- getModSummary $ mkModuleName "B"<br />
p <- parseModule modSum<br />
t <- typecheckModule p<br />
d <- desugarModule t<br />
l <- loadModule d<br />
n <- getNamesInScope<br />
c <- return $ coreModule d<br />
<br />
g <- getModuleGraph<br />
mapM showModule g <br />
return $ (parsedSource d,"/n-----/n", typecheckedSource d)<br />
</haskell><br />
<br />
<haskell><br />
--B.hs<br />
module B where<br />
<br />
main = print "Hello, World!"<br />
<br />
</haskell><br />
<br />
== Further reading ==<br />
<br />
* [http://www.haskell.org/ghc/docs/latest/html/libraries/ghc/index.html GHC API haddock]<br />
* Blog posts from "(parentheses)": [http://parenz.wordpress.com/2013/08/17/ghc-api-interpreted-compiled-and-package-modules/ GHC API: Interpreted, compiled and package modules], [http://parenz.wordpress.com/2013/07/29/ghc-packagedb/ Adding a package database to the GHC API session], [http://parenz.wordpress.com/2013/07/23/on-custom-error-handlers-for-ghc-api/ On custom error handlers for the GHC API].<br />
* [http://mistuke.wordpress.com/category/vsx/ Great blog post] about using the GHC API to get "QuickInfo" in a Visual Studio binding for Haskell.</div>Simonpjhttps://wiki.haskell.org/index.php?title=GHC/As_a_library&diff=56642GHC/As a library2013-08-22T12:20:40Z<p>Simonpj: /* Links */</p>
<hr />
<div>''For instructions on the GHC API with GHC 6.8 or older please refer to [[GHC/As a library (up to 6.8)]]''<br />
<br />
__TOC__<br />
<br />
== Introduction ==<br />
<br />
GHC's functionality can be useful for more things than just compiling Haskell programs. Important use cases are programs that analyse (and perhaps transform) Haskell code. Others include loading Haskell code dynamically in a GHCi-like manner. For this reason, a lot of GHC's features can be accessed by programs which import the <tt>ghc</tt> package.<br />
<br />
The instructions on this page concern the API of GHC 6.10.1 and above. Please note that the GHC API is still in flux and may change quite significantly between major releases while we (the GHC team) provide new features or simplify certain aspects.<br />
<br />
<br />
== Getting Started ==<br />
<br />
To use the GHC API you need GHC 6.10.1 or above and import the <tt>ghc</tt> package.<br />
<pre><br />
ghc -package ghc my_program.hs<br />
</pre><br />
In most cases you probably also want to use the [http://hackage.haskell.org/cgi-bin/hackage-scripts/package/ghc-paths ghc-paths package].<br />
<br />
Most of the common functionality is provided by the <tt>GHC</tt> module, but occasionally you may have to import other modules. See the GHC's [http://www.haskell.org/ghc/docs/latest/html/libraries/ghc/index.html haddock documentation] for a list of these modules. One good entry point into the docs is [http://www.haskell.org/ghc/docs/latest/html/libraries/ghc/GHC.html GHC].<br />
== A Simple Example ==<br />
<br />
The following little program essentially does what <tt>ghc --make</tt> does.<br />
<br />
<haskell><br />
{-# LANGUAGE CPP #-}<br />
import GHC<br />
import GHC.Paths ( libdir )<br />
import DynFlags<br />
<br />
main = <br />
#if __GLASGOW_HASKELL__ > 704<br />
defaultErrorHandler defaultFatalMessager defaultFlushOut $ do<br />
#else<br />
defaultErrorHandler defaultLogAction $ do<br />
#endif<br />
runGhc (Just libdir) $ do<br />
dflags <- getSessionDynFlags<br />
setSessionDynFlags dflags<br />
target <- guessTarget "test_main.hs" Nothing<br />
setTargets [target]<br />
load LoadAllTargets<br />
</haskell><br />
<br />
The outermost function, <tt>defaultErrorHandler</tt>, sets up proper exception handlers and prints an error message and exits with exit code 1 if it encounters one of these exceptions.<br />
<br />
Most of GHC's high-level API requires access to a current session. Therefore, these functions require to be called inside a monad that is an instance of the <tt>GhcMonad</tt> typeclass. Two default implementations of this typeclass are <tt>Ghc</tt> and <tt>GhcT</tt>. In the above example we used the <tt>Ghc</tt> monad since we don't need to track any extra state.<br />
<br />
The argument to <tt>runGhc</tt> is a bit tricky. GHC needs this to find its libraries, so the argument must refer to the directory that is printed by <tt>ghc --print-libdir</tt> for the ''same'' version of GHC that the program is being compiled with. Above we therefore use the <tt>ghc-paths</tt> package which provides this for us.<br />
<br />
== Another example ==<br />
<br />
Here we demonstrate calling [http://www.haskell.org/ghc/docs/latest/html/libraries/ghc/GHC.html#v:parseModule parseModule], [http://www.haskell.org/ghc/docs/latest/html/libraries/ghc/GHC.html#v:typecheckModule typecheckModule], [http://www.haskell.org/ghc/docs/latest/html/libraries/ghc/GHC.html#v:desugarModule desugarModule], [http://www.haskell.org/ghc/docs/latest/html/libraries/ghc/GHC.html#v:getNamesInScope getNamesInScope], and [http://www.haskell.org/ghc/docs/latest/html/libraries/ghc/GHC.html#v:getModuleGraph getModuleGraph]. This works for haskell-platform, ghc-7.0.3 to ghc-7.6.x. It also demonstrates how to enable some extensions.<br />
<br />
<haskell><br />
--A.hs<br />
--invoke: ghci -package ghc A.hs<br />
<br />
{-# LANGUAGE CPP #-}<br />
import GHC<br />
import Outputable<br />
<br />
import GHC.Paths ( libdir )<br />
--GHC.Paths is available via cabal install ghc-paths<br />
<br />
import DynFlags<br />
targetFile = "B.hs"<br />
<br />
main = do<br />
res <- example<br />
#if __GLASGOW_HASKELL__ > 704<br />
putStrLn $ showSDoc tracingDynFlags ( ppr res )<br />
#else<br />
putStrLn $ showSDoc ( ppr res )<br />
#endif<br />
<br />
example = <br />
#if __GLASGOW_HASKELL__ > 704<br />
defaultErrorHandler defaultFatalMessager defaultFlushOut $ do<br />
#else<br />
defaultErrorHandler defaultLogAction $ do<br />
#endif<br />
runGhc (Just libdir) $ do<br />
dflags <- getSessionDynFlags<br />
let dflags' = foldl xopt_set dflags<br />
[Opt_Cpp, Opt_ImplicitPrelude, Opt_MagicHash]<br />
setSessionDynFlags dflags'<br />
target <- guessTarget targetFile Nothing<br />
setTargets [target]<br />
load LoadAllTargets<br />
modSum <- getModSummary $ mkModuleName "B"<br />
p <- parseModule modSum<br />
t <- typecheckModule p<br />
d <- desugarModule t<br />
l <- loadModule d<br />
n <- getNamesInScope<br />
c <- return $ coreModule d<br />
<br />
g <- getModuleGraph<br />
mapM showModule g <br />
return $ (parsedSource d,"/n-----/n", typecheckedSource d)<br />
</haskell><br />
<br />
<haskell><br />
--B.hs<br />
module B where<br />
<br />
main = print "Hello, World!"<br />
<br />
</haskell><br />
<br />
== Links ==<br />
<br />
* [http://www.haskell.org/ghc/docs/latest/html/libraries/ghc/index.html GHC API haddock]<br />
* Blog posts from "(parentheses)": [http://parenz.wordpress.com/2013/08/17/ghc-api-interpreted-compiled-and-package-modules/ GHC API: Interpreted, compiled and package modules], [http://parenz.wordpress.com/2013/07/29/ghc-packagedb/ Adding a package database to the GHC API session], [http://parenz.wordpress.com/2013/07/23/on-custom-error-handlers-for-ghc-api/ On custom error handlers for the GHC API].<br />
* [http://mistuke.wordpress.com/category/vsx/ Great blog post] about using the GHC API to get "QuickInfo" in a Visual Studio binding for Haskell.</div>Simonpjhttps://wiki.haskell.org/index.php?title=Library_submissions&diff=56483Library submissions2013-07-31T22:15:49Z<p>Simonpj: /* The Core Libraries */</p>
<hr />
<div>This page describes the process for maintaining the <br />
'''Core libraries'''. The core libraries are a subset of the packages in the<br />
Haskell Platform, and define basic APIs that are expected to be<br />
available in any Haskell implementation. They are listed under "The Core Libraries" below.<br />
<br />
Non-core libraries are, of course, managed by their own authors/maintainers (named in their .cabal file), using whatever policies those maintainers see fit. [Note: arguably the policies below might usefully be applied to all libraries embodied in the Haskell Platform, but that is a question for the HP team.]<br />
<br />
= General principles =<br />
<br />
* Each core package has a named maintainer, or small group of maintainers, who have commit access to the package. <br />
<br />
* Third parties are encouraged to make proposals for changes, both to the library API and its implementation, by sending the proposal to the maintainer (CC'ing the libraries mailing list).<br />
<br />
* The maintainer is trusted to decide what changes to make to the package, and when. They are strongly encouraged to follow the guidance below, but the general principle is: the community offers opinions, but the maintainers decide.<br />
<br />
<br />
= Responsiveness =<br />
<br />
* Third parties submitting proposals to the maintainer of a library can expect a timely and thoughtful response. <br />
* The more effort the proposer invests (for example, by constructing a patch rather than making an off-the-cuff suggestion) the more consideration s/he can reasonably expect.<br />
* Proposals that have widespread support, and are accompanied by patches (preferably with tests and documentation), should normally be accepted by the maintainer. <br />
* It is up to the maintainer to decide what "widespread" means; in particular, it does not always mean "a majority of those who responded". The majority-responder story is vulnerable to selection bias; e.g. 7 people (out of a client base of hundreds) say "add this function" but the maintainer thinks it will make the interface incrementally more complicated without sufficient benefit.<br />
* Where there is significant work involved in implementing a proposal, it is reasonable for a maintainer to ask for a patch. The principle is that maintainers are not obliged to do the work of implementing a proposal, even if it does enjoy wide support. For more substantial changes, it makes sense to develop the implementation in dialogue with the maintainer.<br />
<br />
= Guidance for proposers =<br />
<br />
A "proposal" can be anything from a one-sentence suggestion to a fully-implemented, tested, and documented patch.<br />
However, the more substantial the proposal the more attention you can expect. The process is this:<br />
<br />
* Send your proposal by email to the maintainer, with a copy to the libraries@haskell.org mailing list (which you need to [http://www.haskell.org/mailman/listinfo/libraries subscribe] to before posting).<br />
<br />
* Set a deadline for discussion (no less than two weeks), and act as chair/moderator for the discussion. <br />
<br />
* At the end of the discussion period, summarise your understanding of the consensus (or lack thereof), including a link to the thread in the mailing list archives, and send the summary to the maintainer for decision. The deadline gives you a moment to summarise the debate and hand over to the maintainer. It isn't a deadline for the maintainer to decide; for example he or she may seek more discussion first. <br />
<br />
* If the decision is positive, [http://hackage.haskell.org/trac/ghc/newticket create a ticket] on the GHC trac. The description of the ticket can summarise the proposal and link to the mail thread. Further discussion and implementation patches can be attached to the ticket, and the ticket helps the maintainer to keep track of what is on the go. (Obviously if the maintainer prefers some other mechanism, follow his or her guidance.)<br />
<br />
* For non-trivial changes the maintainer may ask for a patch. You may create the patch up front, and make it part of your proposal; or you may want to have some discussion about the design first, and only then roll up your sleeves to do the implementation; and for bigger jobs you may want to wait until the maintainer agrees in principle with the change.<br />
<br />
Here are desirable properties for a proposal and its implementation. The more of these properties your proposal or patch has, the more likely it is that the maintainer will adopt your idea. After all, to adopt it the maintainter will have to do whatever tasks you didn't do.<br />
<br />
* '''Description'''. A good proposal says clearly ''what'' you propose, ''why'' it is a good idea, and what its consequences would be.<br />
* '''Patch'''. Use <tt>darcs record</tt> or <tt>git commit</tt> (depending on what sort of repo the library lives in) to create it. Save the patch to a file, using <tt>darcs send --output</tt> or <tt>git format-patch</tt>. Make your changes against a copy of the master branch of the relevant library, and make sure it compiles.<br />
* '''Portability'''. Good code is portable. In particular, try to ensure the code runs in Hugs and GHC, and on Windows and Linux.<br />
* '''Style'''. Good code follows the conventions in the library you are modifying.<br />
* '''Documentation'''. Good code includes valid [http://haskell.org/haddock Haddock] documentation.<br />
* '''Tests'''. Good patches have suitable tests for the library's testsuite.<br />
<br />
= Guidance for maintainers =<br />
<br />
The principle is that we '''trust the maintainer''' to behave sensibly. The guidelines below are just that: guidelines, not rules. Still, the core libraries are used by many, many people, so maintainers should make every effort not to mess them up by accident. <br />
<br />
* '''API changes should be discussed''' on the libraries mailing list prior to making the change, even if the maintainer is the proposer. The maintainer still has ultimate say in what changes are made, but the community should have the opportunity to comment on changes. However, unanimity (or even a majority) is not required.<br />
<br />
* '''Every API change should be described precisely in the commit log.''' The commit logs should be sent to a public mailing list, or otherwise made easily available (e.g. via github), so that the community can keep an eye on changes and comment.<br />
<br />
* '''Backwards compatibility''' is important to many users. API changes are expected to retain backwards compatibility wherever possible. However, from time to time we may decide to have major revisions which are explicitly not backwards compatible; in these cases we may try to make the previous version of the package available concurrently, as in the base-3/base-4 switchover.<br />
<br />
* You don't need to consult the community for '''purely internal changes'''; i.e. changes that do not affect the library's clients.<br />
<br />
* Changes that simply '''widen the API by adding new functions''' are a bit of a grey area. It's better to consult the community, because there may be useful feedback about (say) the order of arguments, or the name of the function, or whatnot. On the other hand few clients will actually break if you add a new function to the API. Use your judgment.<br />
<br />
Libraries maintained by the GHC team are subject to the GHC validation policy - patches will be tested for validation before committing ([http://hackage.haskell.org/trac/ghc/wiki/TestingPatches TestingPatches]). Those packages not maintained by the GHC team will probably have a GHC lagging mirror repository that is subject to validation.<br />
<br />
= The Core Libraries =<br />
<br />
The following packages constitute the core libraries:<br />
<br />
{| border="1"<br />
! Package !! Maintainer<br />
|-<br />
| [http://hackage.haskell.org/package/array array] || Core Libraries Committee<br />
|-<br />
| [http://hackage.haskell.org/package/base base] || Core Libraries Committee<br />
|-<br />
| [http://hackage.haskell.org/package/containers containers] || Johan Tibell and Milan Straka<br />
|-<br />
| [http://hackage.haskell.org/package/deepseq deepseq] || Simon Marlow<br />
|-<br />
| [http://hackage.haskell.org/package/directory directory] || Core Libraries Committee<br />
|-<br />
| [http://hackage.haskell.org/package/extensible-exceptions extensible-exceptions] || Core Libraries Committee <br />
|-<br />
| [http://hackage.haskell.org/package/ghc-prim ghc-prim] || GHC HQ<br />
|-<br />
| [http://hackage.haskell.org/package/hpc hpc] || Andy Gill <br />
|-<br />
| [http://hackage.haskell.org/package/mtl mtl] || Edward Kmett<br />
|-<br />
| [http://hackage.haskell.org/package/parallel parallel] || Simon Marlow<br />
|-<br />
| [http://hackage.haskell.org/package/pretty pretty] || David Terei<br />
|-<br />
| [http://hackage.haskell.org/package/process process] || Core Libraries Committee <br />
|-<br />
| [http://hackage.haskell.org/package/random random] || Ryan Newton<br />
|-<br />
| [http://hackage.haskell.org/package/template-haskell template-haskell] || Core Libraries Committee<br />
|-<br />
| [http://hackage.haskell.org/package/time time] || Ashley Yakeley<br />
|-<br />
| [http://hackage.haskell.org/package/unix unix] || Core Libraries Committee<br />
|-<br />
| [http://hackage.haskell.org/package/Win32 Win32] || Bryan O'Sullivan<br />
|-<br />
| [http://hackage.haskell.org/package/xhtml xhtml] || Chris Dornan<br />
|}<br />
<br />
The maintainer "GHC HQ" means Simon Marlow, Simon Peyton Jones, and Ian Lynagh. Daniel Fischer has taken responsibility for numeric stuff. Email ghc-devs@haskell.org<br />
<br />
The [http://www.haskell.org/haskellwiki/Core_Libraries_Committee Core Libraries Committee] was formed to provide a maintainer of many of the packages previously managed by GHC HQ and can be reached by emailing core-libraries-committee@haskell.org<br />
<br />
The following packages match the appropriate language standard, and as such cannot change independently. The code is maintained by the GHC team.<br />
<br />
{| border="1"<br />
|-<br />
| [http://hackage.haskell.org/package/haskell2010 haskell2010] || GHC HQ<br />
|-<br />
| [http://hackage.haskell.org/package/haskell98 haskell98] || GHC HQ<br />
|}<br />
<br />
These packages are maintained only for backward compatibility, and are not expected to undergo API changes in the future. <br />
<br />
{| border="1"<br />
|-<br />
| [http://hackage.haskell.org/package/old-locale old-locale] || Core Libraries Committee <br />
|-<br />
| [http://hackage.haskell.org/package/old-time old-time] || Core Libraries Committee <br />
|}<br />
<br />
= See also =<br />
<br />
* [http://hackage.haskell.org/trac/ghc/wiki/WorkingConventions GHC Working Conventions], including guidelines for submitting patches via darcs.<br />
* [http://haskell.org/haskellwiki/Category:Style Notes on programming style]<br />
<br />
[[Category:Community]]<br />
[[Category:Proposals| ]]</div>Simonpjhttps://wiki.haskell.org/index.php?title=Performance&diff=55474Performance2013-02-23T10:11:43Z<p>Simonpj: Don Stewart's stack-overflow link</p>
<hr />
<div>{{Performance infobox}}<br />
Welcome to the '''Haskell Performance Resource''', the collected wisdom on how to make your Haskell programs go faster. <br />
<br />
== Introduction ==<br />
<br />
One question that often comes up is along the general lines of "Can I write this program in Haskell so that it performs as well as, or better than, the same program written in some other language?"<br />
<br />
This is a difficult question to answer in general because Haskell is a language, not an implementation. Performance can only be measured relative to a specific language implementation.<br />
<br />
Moreover, it's often not clear if two programs which supposedly have the same functionality really do the same thing. Different languages sometimes require very different ways of expressing the same intent. Certain types of bug are rare in typical Haskell programs that are more common in other languages and vice versa, due to strong typing, automatic memory management and lazy evaluation.<br />
<br />
Nonetheless, it is usually possible to write a Haskell program that performs as well as, or better than, the same program written in any other language. The main caveat is that you may have to modify your code significantly in order to improve its performance. Compilers such as GHC are good at eliminating layers of abstraction, but they aren't perfect, and often need some help. <br />
<br />
There are many non-invasive techniques: compiler options, for example. Then there are techniques that require adding some small amounts of performance cruft to your program: strictness annotations, for example. If you still don't get the best performance, though, it might be necessary to resort to larger refactorings.<br />
<br />
Sometimes the code tweaks required to get the best performance are non-portable, perhaps because they require language extensions that aren't implemented in all compilers (e.g. unboxing), or because they require using platform-specific features or libraries. This might not be acceptable in your setting.<br />
<br />
If the worst comes to the worst, you can always write your critical code in C and use the FFI to call it. Beware of the boundaries though - marshaling data across the FFI can be expensive, and multi-language memory management can be complex and error-prone. It's usually better to stick to Haskell if possible.<br />
<br />
== Basic techniques ==<br />
<br />
The key tool to use in making your Haskell program run faster is ''profiling''. Profiling is provided by [[GHC]] and [[nhc98]]. There is ''no substitute'' for finding where your program's time/space is ''really'' going, as opposed to where you imagine it is going.<br />
<br />
Another point to bear in mind: By far the best way to improve a program's performance ''dramatically'' is to use better algorithms. Once profiling has thrown the spotlight on the guilty time-consumer(s), it may be better to re-think your program than to try all the tweaks listed below.<br />
<br />
Another extremely efficient way to make your program snappy is to use library code that has been Seriously Tuned By Someone Else. You ''might'' be able to write a better sorting function than the one in <tt>Data.List</tt>, but it will take you much longer than typing <tt>import Data.List</tt>.<br />
<br />
We have chosen to organise the rest of this resource first by Haskell construct (data types, pattern matching, integers), and then within each category to describe techniques that apply across implementations, and also techniques that are specific to a certain Haskell implementation (e.g. GHC). There are some implementation-specific techniques that apply in general - those are linked from the [[Haskell Performance Resource#General_Implementation-Specific_Techniques | General Implementation-Specific Techniques]] section below.<br />
<br />
== Haskell constructs ==<br />
<br />
* [[/Data Types/]]<br />
* [[/Functions/]]<br />
* [[/Overloading/]]<br />
* [[/FFI/]]<br />
* [[/Arrays/]]<br />
* [[/Strings/]]<br />
* [[/Integers/]]<br />
* [[/IO | I/O ]]<br />
* [[/Floating Point/]]<br />
* [[/Concurrency/]]<br />
* [[/Modules/]]<br />
* [[/Monads/]]<br />
<br />
== General techniques ==<br />
<br />
* [[/Strictness/]]<br />
* [[/Laziness/]]<br />
* [[/Space | Avoiding space leaks]]<br />
* [[/Accumulating parameter|Accumulating parameters]]<br />
* [[Stack_overflow|Avoiding stack overflow]]<br />
<br />
== Compiler specific techniques ==<br />
<br />
* [[/GHC/]]<br />
* [[/NHC98| nhc98]]<br />
* [[/Hugs/]]<br />
* [[/Yhc/]]<br />
* [[/JHC/]]<br />
<br />
== More information ==<br />
<br />
* Don Stewart's [http://stackoverflow.com/questions/3276240/tools-for-analyzing-performance-of-a-haskell-program/3276557#3276557 Haskell performance overview] on StackOverflow (2013)<br />
* There are plenty of good examples of Haskell code written for performance in the [http://shootout.alioth.debian.org/ The Computer Language Shootout Benchmarks]<br />
* And many alternatives, with discussion, on the [http://web.archive.org/web/20060209215702/http://haskell.org/hawiki/ShootoutEntry old Haskell wiki]<br />
* There are ~100 [http://blog.johantibell.com/2010/09/slides-from-my-high-performance-haskell.html slides on High-Performance Haskell] from the 2010 CUFP tutorial on that topic.<br />
<br />
== Specific comparisons of data structures ==<br />
=== Data.Sequence vs. lists ===<br />
<br />
Data.Sequence has complexity O(log(min(i,n-i))) for access, insertion and update to position i of a sequence of length n.<br />
<br />
List has complexity O(i).<br />
<br />
List is a non-trivial constant-factor faster for operations at the head (cons and head), making it a more efficient choice for stack-like and stream-like access patterns. Data.Sequence is faster for every other access pattern, such as queue and random access.<br />
<br />
See the following program for proof:<br />
<haskell><br />
import Data.Sequence<br />
<br />
insert_million 0 sequence = sequence<br />
insert_million n sequence = insert_million (n - 1)(sequence |> n)<br />
<br />
main = print (Data.Sequence.length (insert_million 1000000 empty))<br />
</haskell><br />
<pre><br />
$ ghc -O2 --make InsertMillionElements.hs && time ./InsertMillionElements +RTS -K100M<br />
1000000<br />
real 0m7.238s<br />
user 0m6.804s<br />
sys 0m0.228s<br />
</pre><br />
<haskell><br />
insert_million 0 list = reverse list<br />
insert_million n list = insert_million (n -1) (n:list)<br />
<br />
main = print (length (insert_million 1000000 []))<br />
</haskell><br />
<pre><br />
$ ghc -O2 --make InsertMillionElements.hs && time ./InsertMillionElementsList +RTS -K100M<br />
1000000<br />
real 0m0.588s<br />
user 0m0.528s<br />
sys 0m0.052s<br />
</pre><br />
Lists are substantially faster on this micro-benchmark.<br />
<br />
A sequence uses between 5/6 and 4/3 times as much space as the equivalent list (assuming an overhead of one word per node, as in GHC).<br />
If only deque operations are used, the space usage will be near the lower end of the range, because all internal nodes will be ternary.<br />
Heavy use of split and append will result in sequences using approximately the same space as lists.<br />
In detail:<br />
* a list of length ''n'' consists of ''n'' cons nodes, each occupying 3 words.<br />
* a sequence of length ''n'' has approximately ''n''/(''k''-1) nodes, where ''k'' is the average arity of the internal nodes (each 2 or 3). There is a pointer, a size and overhead for each node, plus a pointer for each element, i.e. ''n''(3/(''k''-1) + 1) words.<br />
<br />
== Additional Tips ==<br />
<br />
* Use strict returns ( return $! ...) unless you absolutely need them lazy.<br />
* Profile, profile, profile - understand who is hanging on to the memory (+RTS -hc) and how it's being used (+RTS -hb).<br />
* Use +RTS -p to understand who's doing all the allocations and where your time is being spent.<br />
* Approach profiling like a science experiment - make one change, observe if anything is different, rollback and make another change - observe the change. Keep notes!<br />
* Use [[ThreadScope]] to visualize GHC eventlog traces.<br />
<br />
[[Category:Idioms]]<br />
[[Category:Language]]<br />
[[Category:Performance|*]]</div>Simonpjhttps://wiki.haskell.org/index.php?title=GHC/Type_system/PolyKinds&diff=54602GHC/Type system/PolyKinds2012-11-07T04:54:10Z<p>Simonpj: New page: = Kind polymorphism = GHC 7.6 introduced kind polymorphism and data kinds for the first time. This page contains notes (currently rather random) about how to use these features. * User ...</p>
<hr />
<div>= Kind polymorphism =<br />
<br />
GHC 7.6 introduced kind polymorphism and data kinds for the first time. This page contains notes (currently rather random) about how to use these features.<br />
<br />
* User manual sections about [http://www.haskell.org/ghc/docs/latest/html/users_guide/kind-polymorphism.html kind polymorphism] and [http://www.haskell.org/ghc/docs/latest/html/users_guide/promotion.html data type promotion]<br />
* [http://research.microsoft.com/en-us/people/dimitris/fc-kind-poly.pdf Giving Haskell a promotion], the paper about it.<br />
<br />
== Syntactic ambiguity for lists ==<br />
<br />
Suppose <hask>Proxy :: forall k. k -> *</hask>, and consider<br />
<haskell><br />
Proxy [Int]<br />
Proxy [Int,Bool]<br />
</haskell><br />
The former must mean what it always means in Haskell, namely <br />
<haskell><br />
Proxy * (List Int)<br />
</haskell><br />
where I'm writing the kind argument explicitly. To be fully clear, I'm writing <hask>List</hask> for the type constructor for lists (written <hask>[]</hask> in Haskell), so <hask>(List Int)</hask> is a type of kind *.<br />
<br />
But <hask>Proxy [Int,Bool]</hask> can only mean <hask>Proxy</hask> applied to a list of types, thus:<br />
<haskell><br />
Proxy [*] (Cons * Int (Cont * Bool (Nil *)))<br />
</haskell><br />
Now we can see that <hask>Proxy [Int]</hask> is ambiguous. It could also mean<br />
<haskell><br />
Proxy [*] (Cons * Int (Nil *))<br />
</haskell><br />
but we choose the normal meaning to avoid screwing up Haskell programs. To get the above form we have to quote the "[", thus<br />
<haskell><br />
Proxy '[ Int ]<br />
</haskell><br />
In short, singleton lists (and indeed the empty list) must be explicitly promoted with a quote, whereas for type-level lists of two or more elements you don't need an explicit promotion quote.</div>Simonpjhttps://wiki.haskell.org/index.php?title=GHC/Type_system&diff=54583GHC/Type system2012-10-31T16:43:17Z<p>Simonpj: </p>
<hr />
<div>[[Category:GHC|Type system]]<br />
<span style='font-size: x-large; font-weight: bold'>Type system extensions in GHC</span><br />
<br />
GHC comes with a rather large collection of type-system extensions (beyond Haskell 98). They are all documented in the [http://www.haskell.org/ghc/docs/latest/html/users_guide/ghc-language-features.html user manual], but this page is a place to record user-oriented observations, notes, and suggestions on how to use them.<br />
<br />
* '''[[GHC/Indexed_types|Indexed data types]]'''<br />
* '''[[GHC/TypeHoles|Agda-like "holes" in GHC]]'''<br />
* '''[[GHC/Stand-alone deriving declarations|"Stand-alone deriving" declarations]]'''<br />
* '''[[GHC/TypeSigsAndAmbiguity|Type signatures and ambiguity]]'''<br />
* '''Overlapping instances'''. GHC supports overlapping instances, with carefully specified rules. Make sure you read the [http://www.haskell.org/ghc/docs/latest/html/users_guide/type-class-extensions.html#instance-decls relevant sections of the user manual]. Here is an appliation note about [[GHC/AdvancedOverlap|advanced use of overlapping instances]], combined with functional dependencies.</div>Simonpjhttps://wiki.haskell.org/index.php?title=GHC/Type_system&diff=54582GHC/Type system2012-10-31T16:41:41Z<p>Simonpj: </p>
<hr />
<div>[[Category:GHC|Type system]]<br />
<span style='font-size: x-large; font-weight: bold'>Type system extensions in GHC</span><br />
<br />
GHC comes with a rather large collection of type-system extensions (beyond Haskell 98). They are all documented in the [http://www.haskell.org/ghc/docs/latest/html/users_guide/ghc-language-features.html user manual], but this page is a place to record user-oriented observations, notes, and suggestions on how to use them.<br />
<br />
* '''[[GHC/Indexed_types|Indexed data types]]'''<br />
* '''[[GHC/TypeHoles|Agda-like "holes" in GHC]]'''<br />
* '''[[GHC/Stand-alone deriving declarations|"Stand-alone deriving" declarations]]'''<br />
* '''[[GHC/TypeSigsAndAmbituity|Type signatures and ambiguity]]'''<br />
* '''Overlapping instances'''. GHC supports overlapping instances, with carefully specified rules. Make sure you read the [http://www.haskell.org/ghc/docs/latest/html/users_guide/type-class-extensions.html#instance-decls relevant sections of the user manual]. Here is an appliation note about [[GHC/AdvancedOverlap|advanced use of overlapping instances]], combined with functional dependencies.</div>Simonpjhttps://wiki.haskell.org/index.php?title=GHC/Type_system&diff=54581GHC/Type system2012-10-31T16:40:38Z<p>Simonpj: </p>
<hr />
<div>[[Category:GHC|Type system]]<br />
<span style='font-size: x-large; font-weight: bold'>Type system extensions in GHC</span><br />
<br />
GHC comes with a rather large collection of type-system extensions (beyond Haskell 98). They are all documented in the [http://www.haskell.org/ghc/docs/latest/html/users_guide/ghc-language-features.html user manual], but this page is a place to record user-oriented observations, notes, and suggestions on how to use them.<br />
<br />
* [[GHC/Indexed_types|Indexed data types]]<br />
* [[GHC/TypeHoles|Agda-like "holes" in GHC]]<br />
* '''[[GHC/Stand-alone deriving declarations|"stand-alone deriving" declarations]]'''<br />
* [[GHC/TypeSigsAndAmbituity|Type signatures and ambiguity]]<br />
* '''Overlapping instances'''. GHC supports overlapping instances, with carefully specified rules. Make sure you read the [http://www.haskell.org/ghc/docs/latest/html/users_guide/type-class-extensions.html#instance-decls relevant sections of the user manual]. Here is an appliation note about [[GHC/AdvancedOverlap|advanced use of overlapping instances]], combined with functional dependencies.</div>Simonpjhttps://wiki.haskell.org/index.php?title=GHC/Type_system&diff=54580GHC/Type system2012-10-31T16:36:38Z<p>Simonpj: /* Type signatures and ambiguity */</p>
<hr />
<div>[[Category:GHC|Type system]]<br />
<span style='font-size: x-large; font-weight: bold'>Type system extensions in GHC</span><br />
<br />
GHC comes with a rather large collection of type-system extensions (beyond Haskell 98). They are all documented in the [http://www.haskell.org/ghc/docs/latest/html/users_guide/ghc-language-features.html user manual], but this page is a place to record observations, notes, and suggestions on them.<br />
<br />
<br />
<br />
== Overlapping instances ==<br />
<br />
GHC supports overlapping instances, with carefully specified rules. Make sure you read the [http://www.haskell.org/ghc/docs/latest/html/users_guide/type-class-extensions.html#instance-decls relevant sections of the user manual].<br />
<br />
Here is an appliation note about [[GHC/AdvancedOverlap|advanced use of overlapping instances]], combined with functional dependencies.<br />
<br />
== Indexed data types and indexed newtypes ==<br />
<br />
[[GHC/Indexed_types|Indexed data types]] (including associated data types) are a very recent addition to GHC's type system extensions that is not yet included in the user manual. To use the extension, you need to obtain a version of GHC from [http://hackage.haskell.org/trac/ghc/wiki/Building/GettingTheSources its source repository].<br />
<br />
== Stand-alone deriving clauses ==<br />
<br />
Bjorn Bringert has recently implemented [[GHC/Stand-alone deriving declarations|"stand-alone deriving" declarations]]. <br />
<br />
== Type holes ==<br />
<br />
Simon Peyton Jones, Sean Leather and Thijs Alkemade implemented [[GHC/TypeHoles|Agda-like "holes" in GHC]], which will ship in GHC 7.8.1.<br />
<br />
-----------------------</div>Simonpjhttps://wiki.haskell.org/index.php?title=GHC/TypeSigsAndAmbiguity&diff=54579GHC/TypeSigsAndAmbiguity2012-10-31T16:36:23Z<p>Simonpj: New page: == Type signatures and ambiguity == It's quite common for people to write a function definition without a type signature, load it into GHCi, use <tt>:t</tt> to see what type it has, and t...</p>
<hr />
<div>== Type signatures and ambiguity ==<br />
<br />
It's quite common for people to write a function definition without a type signature, load it into GHCi, use <tt>:t</tt> to see what type it has, and then cut-and-paste that type into the source code as a type signature. Usually this works fine, but alas not always. Perhaps this is a deficiency in GHC, but here's one way it can happen:<br />
<haskell><br />
class C a b where<br />
foo :: a -> b<br />
<br />
konst :: a -> Bool<br />
konst x = True<br />
<br />
f :: (C a b) => a -> Bool<br />
f x = konst (foo x)<br />
</haskell><br />
If you compile this code, you'll get this error:<br />
<pre><br />
Foo1.hs:12:13:<br />
Could not deduce (C a b1) from the context (C a b)<br />
arising from use of `foo' at Foo1.hs:12:13-17<br />
Possible fix: add (C a b1) to the type signature(s) for `f'<br />
In the first argument of `konst', namely `(foo x)'<br />
In the expression: konst (foo x)<br />
In the definition of `f': f x = konst (foo x)<br />
</pre><br />
What's going on? GHC knows, from the type signature that <tt>x::a</tt>. Then applying <tt>foo</tt> means GHC must pick a return type for <tt>foo</tt>, say <tt>b1</tt>, and generates the type constraint <tt>(C a b1)</tt>. The function <tt>konst</tt> just discards its argument, ''so nothing further is known about <tt>b1</tt>''. <br />
<br />
Now GHC finished typechecking the right hand side of <tt>f</tt>, so next it checks that the constraints ''needed'' in the RHS, namely <tt>(C a b1)</tt>, can be satisfied from the constraints ''provided'' by the type signature, namely <tt>(C a b)</tt>. Alas there is nothing to tell GHC that <tt>b</tt> and <tt>b1</tt> should be identified together; hence the complaint. (Probably you meant to put a functional dependency in the class declaration, thus<br />
<haskell><br />
class C a b | a->b where ...<br />
</haskell><br />
but you didn't.)<br />
<br />
The surprise is that if you comment out the type signature for <tt>f</tt>, the module will load fine into GHCi! Furthermore <tt>:t</tt> will report a type for <tt>f</tt> that is exactly the same as the type signature that was rejected!<br />
<br />
Here's what's happening. Without the type signature, GHC picks an arbitrary type for <tt>x</tt>, say <tt>x::a</tt>. Then applying <tt>foo</tt> means GHC must pick a return type for <tt>foo</tt>, say <tt>b</tt>, and generates the type constraint <tt>(C a b)</tt>. The function <tt>konst</tt> just discards its argument, so nothing further is known about <tt>b</tt>. Finally, GHC gathers up all the constraints arising from the right hand side, namely <tt>(C a b)</tt>, and puts them into the inferred type of <tt>f</tt>. So GHC ends up saying that <hask>f :: (C a b) => a -> Bool</hask>. <br />
<br />
This is probably a very stupid type. Suppose you called <tt>f</tt> thus: <tt>(f 'a')</tt>. Then you'd get a constraint <tt>(C Char b)</tt> where nothing is known about <tt>b</tt>. If the instances of <tt>C</tt> constrain both type parameters, you'd be in trouble:<br />
<haskell><br />
instance C Char Bool where ...<br />
</haskell><br />
The call gives a <tt>(C Char b)</tt> constraint, with absolutely no way to fix <tt>b</tt> to be <tt>Bool</tt>, or indeed anything else. We're back to very much the same situation as before; it's just that the error is deferred until we call <tt>f</tt>, rather than when we define it.<br />
<br />
(However, notice that the call <tt>(f 'a')</tt> would be OK if there was an instance like:<br />
<haskell><br />
instance C Char w where ...<br />
</haskell><br />
Now the constraint <tt>(C Char b)</tt> matches the instance declaration, even though we know nothing about <tt>b</tt>.)<br />
<br />
This behaviour isn't ideal. It really only arises in programs that are ambiguous anyway (that is, they could never really work), but it is undoubtedly confusing. But I don't know an easy way to improve it. Yet, anyway.</div>Simonpjhttps://wiki.haskell.org/index.php?title=GHC/Type_families&diff=45989GHC/Type families2012-06-11T07:46:18Z<p>Simonpj: /* Frequently asked questions */</p>
<hr />
<div>Indexed type families, or '''type families''' for short, are a Haskell extension supporting ad-hoc overloading of data types. Type families are parametric types that can be assigned specialized representations based on the type parameters they are instantiated with. They are the data type analogue of [[Type class|type classes]]: families are used to define overloaded ''data'' in the same way that classes are used to define overloaded ''functions''. Type families are useful for generic programming, for creating highly parameterised library interfaces, and for creating interfaces with enhanced static information, much like dependent types.<br />
<br />
Type families come in two flavors: ''data families'' and ''type synonym families''. Data families are the indexed form of data and newtype definitions. Type synonym families are the indexed form of type synonyms. Each of these flavors can be defined in a standalone manner or ''associated'' with a type class. Standalone definitions are more general, while associated types can more clearly express how a type is used and lead to better error messages.<br />
<br />
''NB: see also Simon's [http://hackage.haskell.org/trac/ghc/blog/LetGeneralisationInGhc7 blog entry on let generalisation] for a significant change in the policy for let generalisation, driven by the type family extension. In brief: a few programs will puzzlingly fail to compile with <tt>-XTypeFamilies</tt> even though the code is legal Haskell 98.''<br />
<br />
== What are type families? ==<br />
<br />
The concept of a type family comes from type theory. An indexed type family in type theory is a partial function at the type level. Applying the function to parameters (called ''type indices'') yields a type. Type families permit a program to compute what data constructors it will operate on, rather than having them fixed statically (as with simple type systems) or treated as opaque unknowns (as with parametrically polymorphic types).<br />
<br />
Type families are to vanilla data types what type class methods are to regular functions. Vanilla polymorphic data types and functions have a single definition, which is used at all type instances. Classes and type families, on the other hand, have an interface definition and any number of instance definitions. A type family's interface definition declares its [[kind]] and its arity, or the number of type indices it takes. Instance definitions define the type family over some part of the domain.<br />
<br />
As a simple example of how type families differ from ordinary parametric data types, consider a strict list type. We can represent a list of <hask>Char</hask> in the usual way, with cons cells. We can do the same thing to represent a list of <hask>()</hask>, but since a strict <hask>()</hask> value carries no useful information, it would be more efficient to just store the length of the list. This can't be done with an ordinary parametric data type, because the data constructors used to represent the list would depend on the list's type parameter: if it's <hask>Char</hask> then the list consists of cons cells; if it's <hask>()</hask>, then the list consists of a single integer. We basically want to select between two different data types based on a type parameter. Using type families, this list type could be declared as follows:<br />
<br />
<haskell><br />
-- Declare a list-like data family<br />
data family XList a<br />
<br />
-- Declare a list-like instance for Char<br />
data instance XList Char = XCons !Char !(XList Char) | XNil<br />
<br />
-- Declare a number-like instance for ()<br />
data instance XList () = XListUnit !Int<br />
</haskell><br />
<br />
The right-hand sides of the two <code>data instance</code> declarations are exactly ordinary data definitions. In fact, a <code>data instance</code> declaration is nothing more than a shorthand for a <code>data</code> declaration followed by a <code>type instance</code> (see below) declaration. However, they define two instances of the same parametric data type, <hask>XList Char</hask> and <hask>XList ()</hask>, whereas ordinary data declarations define completely unrelated types. A recent [[Simonpj/Talk:FunWithTypeFuns|tutorial paper]] has more in-depth examples of programming with type families. <br />
<br />
[[GADT]]s bear some similarity to type families, in the sense that they allow a parametric type's constructors to depend on the type's parameters. However, all GADT constructors must be defined in one place, whereas type families can be extended. Functional dependences are similar to type families, and many type classes that use functional dependences can be equivalently expressed with type families. Type families provide a more functional style of type-level programming than the relational style of functional dependences.<br />
<br />
== What do I need to use type families? ==<br />
<br />
Type families are a GHC extension enabled with the <code>-XTypeFamilies</code> flag or the <code>{-# LANGUAGE TypeFamilies #-}</code> pragma. The first stable release of GHC that properly supports type families is 6.10.1. (The 6.8 release included an early partial implementation, but its use is deprecated.) Please [http://hackage.haskell.org/trac/ghc/query?status=new&status=assigned&status=reopened&group=priority&type=bug&order=id&desc=1 report bugs] via the GHC bug tracker, ideally accompanied by a small example program that demonstrates the problem. Use the [mailto:glasgow-haskell-users@haskell.org GHC mailing list] for questions or for a discussion of this language extension and its description on this wiki page.<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-families.html#data-family-declarations ''kind signature''] (here <hask>* -> *</hask>) for the associated data type <hask>GMap k</hask> - analogous 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.IntMap</hask>, thusly:<br />
<haskell><br />
instance GMapKey Int where<br />
data GMap Int v = GMapInt (Data.IntMap.IntMap v)<br />
empty = GMapInt Data.IntMap.empty<br />
lookup k (GMapInt m) = Data.IntMap.lookup k m<br />
insert k v (GMapInt m) = GMapInt (Data.IntMap.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 fundamental 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 />
Next, 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 b) v (GMapEither gm1 gm2) = GMapEither gm1 (insert b v gm2)<br />
</haskell><br />
If you find this code algorithmically surprising, I'd suggest to have a look at [http://www.cs.ox.ac.uk/ralf.hinze/publications/index.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 querying 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 source code[http://darcs.haskell.org/testsuite/tests/ghc-regress/indexed-types/should_run/GMapAssoc.hs] for <hask>GMap</hask> from GHC's test suite.<br />
<br />
== Detailed definition of data families ==<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-indices to coincide with the class parameters. However, the latter 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> keyword. 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-indices. 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. In other words: '''the named type parameters of the data declaration must be a permutation of a subset of the class variables'''. <br />
<br />
Example is admissible:<br />
<haskell><br />
class C a b c where { data T c a :: * } -- OK<br />
class C a b c where { data T a a :: * } -- Bad: repeated variable<br />
class D a where { data T a x :: * } -- Bad: x is not a class variable<br />
class D a where { data T a :: * -> * } -- OK<br />
</haskell><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, but may not contain forall types or type synonym families. However, data families are generally allowed in type parameters, and type synonyms are allowed as long as they are fully applied and expand to a type that is itself admissible - exactly as this is required for occurrences of type synonyms in class instance parameters. 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 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 />
nonsense :: T a -> Int<br />
nonsense A = 1 -- WRONG: These two equations together...<br />
nonsense 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 - 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 indices corresponding to class parameters must be identical to the type given in the instance head; here this is the 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 instance 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 />
==== Scoping of class parameters ====<br />
<br />
In the case of multi-parameter type classes, the visibility of class parameters in the right-hand side of associated family instances depends ''solely'' on the parameters of the data family. As an example, consider the simple class declaration<br />
<haskell><br />
class C a b where<br />
data T a<br />
</haskell><br />
Only one of the two class parameters is a parameter to the data family. Hence, the following instance declaration is invalid:<br />
<haskell><br />
instance C [c] d where<br />
data T [c] = MkT (c, d) -- WRONG!! 'd' is not in scope<br />
</haskell><br />
Here, the right-hand side of the data instance mentions the type variable <hask>d</hask> that does not occur in its left-hand side. We cannot admit such data instances as they would compromise type safety.<br />
<br />
==== Type class instances of family 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 implicitly 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 is 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>GMapEither</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 />
== An associated type synonym example ==<br />
<br />
Type synonym families are an alternative to functional dependencies, which makes functional dependency examples well suited to introduce type synonym families. In fact, type families are a more functional way to express the same as functional dependencies (despite the name!), as they replace the relational notation of functional dependencies by an expression-oriented notation; i.e., functions on types are really represented by functions and not relations.<br />
<br />
=== The <hask>class</hask> declaration ===<br />
<br />
Here's an example from Mark Jones' seminal paper on functional dependencies:<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 />
Instead of the multi-parameter type class, we use a single parameter class, and the parameter <hask>e</hask><br />
turned into an associated type synonym <hask>Elem ce</hask>.<br />
<br />
=== An <hask>instance</hask>===<br />
<br />
Instances change correspondingly. An instance of the two-parameter class<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) <br />
| e == x = True<br />
| otherwise = member e xs<br />
toList l = l<br />
</haskell><br />
becomes an instance of a single-parameter class, where the dependent type parameter turns into an associated type instance declaration:<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) <br />
| 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 />
== Detailed definition of type synonym families ==<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-indices to coincide with the class parameters. However, the latter 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 />
Parameters can also be given explicit kind signatures if needed. We call the number of parameters in a type family declaration, the family's arity, and all applications of a type family must be fully saturated w.r.t. to that arity. This requirement is unlike ordinary type synonyms and it implies that the kind of a type family is not sufficient to determine a family's arity, and hence in general, also insufficient to determine whether a type family application is well formed. As an example, consider the following declaration:<br />
<haskell><br />
type family F a b :: * -> * -- F's arity is 2, <br />
-- although its overall kind is * -> * -> * -> *<br />
</haskell><br />
Given this declaration the following are examples of well-formed and malformed types:<br />
<haskell><br />
F Char [Int] -- OK! Kind: * -> *<br />
F Char [Int] Bool -- OK! Kind: *<br />
F IO Bool -- WRONG: kind mismatch in the first argument<br />
F Bool -- WRONG: unsaturated application<br />
</haskell><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 />
Exactly as in the case of an associated data declaration, '''the named type parameters must be a permutation of a subset of the class parameters'''. Examples<br />
<haskell><br />
class C a b c where { type T c a :: * } -- OK<br />
class D a where { type T a x :: * } -- No: x is not a class parameter<br />
class D a where { type T a :: * -> * } -- OK<br />
</haskell><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, but may not contain forall types or type synonym families. However, data families are generally allowed, and type synonyms are allowed as long as they are fully applied and expand to a type that is admissible - these are the exact same requirements as for data instances. For example, the <hask>[e]</hask> instance for <hask>Elem</hask> is<br />
<haskell><br />
type instance Elem [e] = e<br />
</haskell><br />
<br />
A type family instance declaration must satisfy the following rules:<br />
* An appropriate family declaration is in scope - just like class instances require the class declaration to be visible. <br />
* The instance declaration conforms to the kind determined by its family declaration<br />
* The number of type parameters in an instance declaration matches the number of type parameters in the family declaration.<br />
* The right-hand side of a type instance must be a monotype (i.e., it may not include foralls) and after the expansion of all saturated vanilla type synonyms, no synonyms, except family synonyms may remain.<br />
<br />
Here are some examples of admissible and illegal type instances:<br />
<haskell><br />
type family F a :: *<br />
type instance F [Int] = Int -- OK!<br />
type instance F String = Char -- OK!<br />
type instance F (F a) = a -- WRONG: type parameter mentions a type family<br />
type instance F (forall a. (a, b)) = b -- WRONG: a forall type appears in a type parameter<br />
type instance F Float = forall a.a -- WRONG: right-hand side may not be a forall type<br />
<br />
type family G a b :: * -> *<br />
type instance G Int = (,) -- WRONG: must be two type parameters<br />
type instance G Int Char Float = Double -- WRONG: must be two type parameters<br />
</haskell><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 instance 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 only overlap if the right-hand sides of the overlapping instances coincide for the overlapping types. More formally, two instance declarations overlap if there is a substitution that makes the left-hand sides of the instances syntactically the same. Whenever that is the case, the right-hand sides of the instances must also be syntactically equal under the same substitution. This condition is independent of whether the type family is associated or not, and it is not only a matter of consistency, but one of type safety.<br />
<br />
Here are two examples to illustrate the condition under which overlap is permitted.<br />
<haskell><br />
type instance F (a, Int) = [a]<br />
type instance F (Int, b) = [b] -- overlap permitted<br />
<br />
type instance G (a, Int) = [a]<br />
type instance G (Char, a) = [a] -- ILLEGAL overlap, as [Char] /= [Int]<br />
</haskell><br />
<br />
==== Decidability ====<br />
<br />
In order to guarantee that type inference in the presence of type families is decidable, we need to place a number of additional restrictions on the formation of type instance declarations (c.f., Definition 5 (Relaxed Conditions) of [http://www.cse.unsw.edu.au/~chak/papers/SPCS08.html Type Checking with Open Type Functions]). Instance declarations have the general form<br />
<haskell><br />
type instance F t1 .. tn = t<br />
</haskell><br />
where we require that for every type family application <hask>(G s1 .. sm)</hask> in <hask>t</hask>, <br />
# <hask>s1 .. sm</hask> do not contain any type family constructors,<br />
# the total number of symbols (data type constructors and type variables) in <hask>s1 .. sm</hask> is strictly smaller than in <hask>t1 .. tn</hask>, and<br />
# for every type variable <hask>a</hask>, <hask>a</hask> occurs in <hask>s1 .. sm</hask> at most as often as in <hask>t1 .. tn</hask>.<br />
These restrictions are easily verified and ensure termination of type inference. However, they are not sufficient to guarantee completeness of type inference in the presence of, so called, ''loopy equalities'', such as <hask>a ~ [F a]</hask>, where a recursive occurrence of a type variable is underneath a family application and data constructor application - see the above mentioned paper for details. <br />
<br />
If the option <tt>-XUndecidableInstances</tt> is passed to the compiler, the above restrictions are not enforced and it is on the programmer to ensure termination of the normalisation of type families during type inference.<br />
<br />
=== Equality constraints ===<br />
<br />
Type context can include equality constraints of the form <hask>t1 ~ t2</hask>, which denote that the types <hask>t1</hask> and <hask>t2</hask> need to be the same. In the presence of type families, whether two types are equal cannot generally be decided locally. Hence, the contexts of function signatures may include equality constraints, as in the following example:<br />
<haskell><br />
sumCollects :: (Collects c1, Collects c2, Elem c1 ~ Elem c2) => c1 -> c2 -> c2<br />
</haskell><br />
where we require that the element type of <hask>c1</hask> and <hask>c2</hask> are the same. In general, the types <hask>t1</hask> and <hask>t2</hask> of an equality constraint may be arbitrary monotypes; i.e., they may not contain any quantifiers, independent of whether higher-rank types are otherwise enabled.<br />
<br />
Equality constraints can also appear in class and instance contexts. The former enable a simple translation of programs using functional dependencies into programs using family synonyms instead. The general idea is to rewrite a class declaration of the form<br />
<haskell><br />
class C a b | a -> b<br />
</haskell><br />
to<br />
<haskell><br />
class (F a ~ b) => C a b where<br />
type F a<br />
</haskell><br />
That is, we represent every functional dependency (FD) <hask>a1 .. an -> b</hask> by an FD type family <hask>F a1 .. an</hask> and a superclass context equality <hask>F a1 .. an ~ b</hask>, essentially giving a name to the functional dependency. In class instances, we define the type instances of FD families in accordance with the class head. Method signatures are not affected by that process.<br />
<br />
NB: Equalities in superclass contexts are not fully implemented in the GHC 6.10 branch.<br />
<br />
== Frequently asked questions ==<br />
<br />
=== Comparing type families and functional dependencies ===<br />
<br />
Functional dependencies cover some of the same territory as type families. How do the two compare? There's a whole [[Functional_dependencies_vs._type_families|wiki page about it]].<br />
<br />
=== Injectivity, type inference, and ambiguity ===<br />
<br />
A common problem is this<br />
<haskell><br />
type family F a<br />
<br />
f :: F a -> F a<br />
f = undefined<br />
<br />
g :: F Int -> F Int<br />
g x = f x<br />
</haskell><br />
The compiler complains about the definition of <tt>g</tt> saying<br />
<haskell><br />
Couldn't match expected type `F Int' against inferred type `F a1'<br />
</haskell><br />
In type-checking <tt>g</tt>'s right hand side GHC discovers (by instantiating <tt>f</tt>'s type with a fresh type variable) that it has type <tt>F a1 -> F a1</tt> for some as-yet-unknown type <tt>a1</tt>. Now it tries to make the inferred type match <tt>g</tt>'s type signature. Well, you say, just make <tt>a1</tt> equal to <tt>Int</tt> and you are done. True, but what if there were these instances<br />
<haskell><br />
type instance F Int = Bool<br />
type instance F Char = Bool<br />
</haskell><br />
Then making <tt>a1</tt> equal to <tt>Char</tt> would ''also'' make the two types equal. Because there is (potentially) more than one choice, the program is rejected.<br />
<br />
However (and confusingly) if you omit the type signature on <tt>g</tt> altogether, thus<br />
<haskell><br />
f :: F a -> F a<br />
f = undefined<br />
<br />
g x = f x<br />
</haskell><br />
GHC will happily infer the type <tt>g :: F a -> F a</tt>. But you can't ''write'' that type signature or, indeed, the more specific one above. (Arguably this behaviour, where GHC ''infers'' a type it can't ''check'', is very confusing. I suppose we could make GHC reject both programs, with and without type signatures.)<br />
<br />
'''What is the problem?''' The nub of the issue is this: knowing that <tt>F t1</tt>=<tt>F t2</tt> does ''not'' imply that <tt>t1</tt> = <tt>t2</tt>.<br />
The difficulty is that the type function <tt>F</tt> need not be ''injective''; it can map two distinct types to the same type. For an injective type constructor like <tt>Maybe</tt>, if we know that <tt>Maybe t1</tt> = <tt>Maybe t2</tt>, then we know that <tt>t1</tt> = <tt>t2</tt>. But not so for non-injective type functions.<br />
<br />
The problem starts with <tt>f</tt>. Its type is ''ambiguous''; even if I know the argument and result types for <tt>f</tt>, I cannot use that to find the type at which <tt>a</tt> should be instantiated. (So arguably, <tt>f</tt> should be rejected as having an ambiguous type, and probably will be in future.) The situation is well known in type classes: <br />
<haskell><br />
bad :: (Read a, Show a) => String -> String<br />
bad x = show (read x)<br />
</haskell><br />
At a call of <tt>bad</tt> one cannot tell at what type <tt>a</tt> should be instantiated.<br />
<br />
The only solution is to avoid ambiguous types. In the type signature of a function, <br />
* Ensure that every type variable occurs in the part after the "<tt>=></tt>"<br />
* Ensure that every type variable appears at least once outside a type function call.<br />
Alternatively, you can use data families, which create new types and are therefore injective. The following code works:<br />
<br />
<haskell>data family F a<br />
<br />
f :: F a -> F a<br />
f = undefined<br />
<br />
g :: F Int -> F Int<br />
g x = f x</haskell><br />
<br />
== See also ==<br />
<br />
* Experiences in converting functional dependencies to type families: "[[Functional dependencies vs. type families]]"<br />
* [http://hackage.haskell.org/trac/ghc/wiki/TFvsFD GHC trac] on a comparison of functional dependencies an type families<br />
<br />
== References ==<br />
<br />
* [http://www.cse.unsw.edu.au/~chak/papers/CKPM05.html Associated Types with Class.] Manuel M. T. Chakravarty, Gabriele Keller, Simon Peyton Jones, and Simon Marlow. In ''Proceedings of The 32nd Annual ACM SIGPLAN-SIGACT Symposium on Principles of Programming Languages (POPL'05)'', pages 1-13, ACM Press, 2005.<br />
* [http://www.cse.unsw.edu.au/~chak/papers/CKP05.html Associated Type Synonyms.] 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 />
* [http://www.cse.unsw.edu.au/~chak/papers/SCPD07.html System F with Type Equality Coercions.] Martin Sulzmann, Manuel M. T. Chakravarty, Simon Peyton Jones, and Kevin Donnelly. In ''Proceedings of The Third ACM SIGPLAN Workshop on Types in Language Design and Implementation'', ACM Press, 2007.<br />
* [http://www.cse.unsw.edu.au/~chak/papers/SPCS08.html Type Checking With Open Type Functions.] Tom Schrijvers, Simon Peyton-Jones, Manuel M. T. Chakravarty, Martin Sulzmann. In ''Proceedings of The 13th ACM SIGPLAN International Conference on Functional Programming'', ACM Press, pages 51-62, 2008.<br />
* [[Simonpj/Talk:FunWithTypeFuns | Fun with Type Functions]] Oleg Kiselyov, Simon Peyton Jones, Chung-chieh Shan (the source for this paper can be found at http://patch-tag.com/r/schoenfinkel/typefunctions/wiki ) <br />
<br />
[[Category:Type-level programming]]<br />
[[Category:Language extensions]]<br />
[[Category:GHC|Indexed types]]</div>Simonpjhttps://wiki.haskell.org/index.php?title=APL&diff=44799APL2012-03-08T13:41:19Z<p>Simonpj: /* The main API, using Plan A */</p>
<hr />
<div>= An APL library for Haskell =<br />
<br />
APL is an array language with a highly-functional flavour, and a rich set of carefully-thought-out array operations. It would be interesting to build a Haskell library that offered a Haskell rendering of APL's array algebra, possibly (though not definitely) bound to a mature implementation.<br />
<br />
This page collects thoughts loosely based around that idea.<br />
<br />
= APL arrays in Haskell =<br />
<br />
<hask><br />
data Array elt -- Forces uniform element types<br />
</hask><br />
<br />
* Need rank-zero arrays<br />
<br />
* In a rank-3 arrary, any of the axes can have zero length<br />
<tt><br />
e.g. (3 x 0 x 4) array /= (0 x 0 x 4) array<br />
</tt><br />
<br />
* Prototypical item? Leave open for now. A minefield.<br />
<br />
Major question: should the rank be visible in the type at all?<br />
<tt><br />
Plan A: data Array elt <br />
Plan (Succ A): data Array rank elt<br />
</tt><br />
<br />
= The main API, using Plan A =<br />
<br />
<haskell><br />
data Array a -- Rectangular!<br />
<br />
type Scalar a = Array a -- Rank 0, length 1<br />
type Vector a = Array a -- Rank 1!<br />
type Matrix a = Array a -- Rank 2!<br />
type Axis = Nat<br />
<br />
-- Arrays can be added, multiplied, etc<br />
class Num a where<br />
(+) :: Num a => a -> a -> <br />
<br />
instance Num a => Num (Array a) where ..<br />
<br />
-- All indexing is 0-based (Dijkstra)<br />
</haskell><br />
<br />
Basic operations<br />
<haskell><br />
-- A rank-0 array contains one item<br />
zilde :: Vector a -- Empty vector, rank 1<br />
enclose :: a -> Scalar a -- Returns a rank 0 array, of<br />
-- depth one greater than input<br />
<br />
encloseA :: Nat -- r<br />
-> Array a -- Rank n<br />
-> Array (Array a) -- Outer rank r, inner rank n-r<br />
-- encloseA 2 (Array [3,1,4]) : Array [3] (Array [1,4])<br />
-- enclose a = encloseA 0 (when a is an array)<br />
<br />
disclose :: Scalar a -> Array a<br />
discloseA :: Array (Array a) -> Array a<br />
<br />
iota :: Nat -> Array Nat -- iota n = [0 1 2 3 ... n-1]<br />
<br />
ravel :: Array a -> Vector a -- Flattens an array of arbitrary rank<br />
-- (including zero!) in row-major order<br />
-- Does not change depth<br />
<br />
reshape :: Vector Nat -- s: the shape<br />
-> Array a -- Arbitrary shape <br />
-> Array a -- Shape of result = s<br />
-- NB: ravel a = product (shape a) `reshape` a<br />
<br />
product :: Num a => a -> Array a -> Array a<br />
productA :: Num a => Axis -> a -> Array a -> Array a<br />
-- Result has rank one smaller than input<br />
<br />
shape :: Array a -> Vector Nat<br />
-- shape [[1 3] [5 2] [3 9]] = [3 2]<br />
-- shape [3 2] = [2] <br />
-- shape [2] = [1] <br />
<br />
-- rank = shape . shape -- Rank 1 and shape [1] <br />
-- Or we could have rank :: Array a -> Nat<br />
</haskell><br />
<br />
Swapping rank and depth<br />
<haskell><br />
rankOperator :: <br />
-- This is in J and it is somehow lovely in a way <br />
-- that ordinary mortals cannot understand<br />
-- rankOp 1 (+) A B<br />
<br />
-- Swapping rank and depth<br />
-- Array [2,4,5,3] Float <br />
-- --> Array [2,5] (Array [4,3] Float)<br />
-- And the reverse!<br />
<br />
rankOp rank-spec f = reshape rank-spec . f . unreshape rank-spec<br />
<br />
<br />
transpose :: Vector Nat -- Permutation of (iota (rank arg))<br />
-> Array a -- Arg<br />
-> Array a<br />
-- Permutes the axes <br />
</haskell><br />
<br />
More operations<br />
<haskell><br />
class Item a wher<br />
depth :: a -> Nat<br />
<br />
instance Item Float where<br />
depth _ = 0<br />
instance Item a => Item (Array a) where<br />
depth _ = 1 + depth (undefined :: a)<br />
<br />
<br />
catenate :: Array a -> Array a -> Array a<br />
-- Concatenates on last axis (or first in J)<br />
-- Checks for shape compatibility<br />
catenateA :: Axis -> Array a -> Array a -> Array a<br />
-- You can specify the axis<br />
<br />
-- Swapping rank with depth<br />
flatten :: Vector (Vector a) -> Array a<br />
<br />
vector :: [a] -> Vector a<br />
<br />
each :: (a -> b) -> Array a -> Array b<br />
<br />
simpleIndex -- m [a;b]<br />
:: Array a -- a: The array to index<br />
-> Vector (Array Nat) -- i: Outer array is a tuple<br />
-- of length = rank a<br />
-> Array a -- shape result = shape i[0] x shape i[1] ....<br />
simpleIndex a is = chooseIndex a (disclose (reduce (outer catenate) zilde is)) <br />
-- We aren't quite sure about this definition<br />
<br />
reduce :: (Array a -> Array a -> Array a) -> Array a<br />
-- All rank one smaller than input<br />
-> Array a -- Input<br />
-> Array a -- Rank one smaller than input<br />
-- except that rank 0 input gives identity<br />
<br />
reduceA :: Axis -> (a -> a -> a) -> a<br />
-> Array a<br />
-> Array a -- Rank one smaller than ieput<br />
<br />
<br />
outer :: (a -> b -> c) -- Function argument<br />
-> Array a -> Array b -- Two array arguments, arg1, arg2<br />
-> Array c -- Shape result = shape arg1 ++ shape arg2<br />
<br />
-- simpleIndex a (vector [enclose 3, enclose 4]) :: Array a (rank 0)<br />
-- mat [3 ; 4]<br />
<br />
chooseIndex -- m [b]<br />
:: Array a -- a: The array to index<br />
-> Array (Vector Nat) -- i: Inner arrays are the index tuples<br />
-- of length = rank a<br />
-> Array a -- shape result = shape i<br />
</haskell><br />
<br />
Various monomorphic pick operators<br />
<haskell><br />
pick1 :: Vector (Matrix (Vector a))<br />
-> Array (Nat, (Nat,Nat), Nat)<br />
-> Array a<br />
<br />
pick2 :: Vector (Matrix a)<br />
-> Array (Nat, (Nat,Nat))<br />
-> Array a<br />
<br />
-- Just an instance of pick2<br />
pick2 :: Vector (Matrix (Vector a))<br />
-> Array (Nat, (Nat,Nat))<br />
-> Array (Vector a)<br />
</haskell><br />
<br />
= Reference implementation =<br />
<br />
This implementation of the above API is intended to give its semantics.<br />
It is not intended to run fast!<br />
<br />
<haskell><br />
data Array a = Arr Shape [a]<br />
<br />
type Shape = [Nat]<br />
-- Invariant: Arr s xs: product s = length xs<br />
<br />
ravel :: Array a -> Vector a<br />
ravel (Arr s a) = Arr [product s] a<br />
<br />
zilde :: Vector a -- Empty vector, rank 1<br />
zilde = Arr [0] []<br />
<br />
enclose :: a -> Scalar a -- Returns a rank 0 array, of<br />
-- depth one greater than input<br />
enclose x = Arr [] [x]<br />
<br />
disclose :: Scalar a -> a <br />
disclose (Arr [] [x]) = x<br />
<br />
discloseA (Arr outer items)<br />
= Arr (outer ++ inner) [ i | Arr _ is <- items, i <- is ] <br />
where<br />
(Arr inner _ : _) = items<br />
<br />
<br />
transpose :: Vector Nat -- Permutation of (iota (rank arg))<br />
-> Array a -- Arg<br />
-> Array a<br />
transpose (Arr [n] perm) (Arr shape items)<br />
= assert (n == length shape ) $<br />
Arr (permute perm shape) <br />
(scramble ... items)<br />
<br />
-- Property: disclose (enclose x) == x<br />
<br />
shape :: Array a -> Vector Nat<br />
shape (Arr s a) = Arr [1] s<br />
<br />
reshape :: Vector Nat -- s: the shape<br />
-> Array a -- Arbitrary shape <br />
-> Array a -- Shape of result = s<br />
reshape (Arr [n] s) (Arr s' elts)<br />
| null elts = error "Reshape on empty array"<br />
| otherwise<br />
= Arr s (take (product s) (cycle elts))<br />
<br />
each :: (a -> b) -> Array a -> Array b<br />
each f (Arr s xs) = Arr s (map f xs)<br />
<br />
reduce :: (Array a -> Array a -> Array a) -> Array a<br />
-- All rank one smaller than input<br />
-> Array a -- Input<br />
-> Array a -- Rank one smaller than input<br />
-- except that rank 0 input gives identity<br />
reduce k z (Arr [] [item])<br />
= Arr [] [item] -- Identity on rank 0<br />
reduce k z (Arr (s:ss) items)<br />
= foldr k z (chop ss items)<br />
<br />
encloseA :: Nat -> Array a -> Array a<br />
encloseA n (Arr shape items)<br />
= Arr outer_shape (chop inner_shape items)<br />
where<br />
(outer_shape, inner_shape) = splitAt n shape<br />
<br />
chop :: Shape -> [item] -> [Array item]<br />
chop s [] = []<br />
chop s is = Arr s i : chop s is'<br />
where<br />
(i,is') = splitAt (product s) is<br />
</haskell><br />
<br />
== A couple of examples == <br />
<br />
<tt><br />
x = 0 1 2 : Array Float = Arr [2,3] [0,1,2,3,4,5]<br />
3 4 5 <br />
<br />
enclose x :: Array (Array Float)<br />
= Arr [] [Arr [2,3] [0,1,2,3,4,5]]<br />
</tt></div>Simonpjhttps://wiki.haskell.org/index.php?title=APL&diff=44792APL2012-03-08T10:35:31Z<p>Simonpj: /* An APL library for Haskell */</p>
<hr />
<div>= An APL library for Haskell =<br />
<br />
APL is an array language with a highly-functional flavour, and a rich set of carefully-thought-out array operations. It would be interesting to build a Haskell library that offered a Haskell rendering of APL's array algebra, possibly (though not definitely) bound to a mature implementation.<br />
<br />
This page collects thoughts loosely based around that idea.<br />
<br />
= APL arrays in Haskell =<br />
<br />
<hask><br />
data Array elt -- Forces uniform element types<br />
</hask><br />
<br />
* Need rank-zero arrays<br />
<br />
* In a rank-3 arrary, any of the axes can have zero length<br />
<tt><br />
e.g. (3 x 0 x 4) array /= (0 x 0 x 4) array<br />
</tt><br />
<br />
* Prototypical item? Leave open for now. A minefield.<br />
<br />
Major question: should the rank be visible in the type at all?<br />
<tt><br />
Plan A: data Array elt <br />
Plan (Succ A): data Array rank elt<br />
</tt><br />
<br />
= The main API, using Plan A =<br />
<br />
<haskell><br />
data Array a -- Rectangular!<br />
<br />
type Scalar a = Array a -- Rank 0, length 1<br />
type Vector a = Array a -- Rank 1!<br />
type Matrix a = Array a -- Rank 2!<br />
type Axis = Nat<br />
<br />
-- Arrays can be added, multiplied, etc<br />
class Num a where<br />
(+) :: Num a => a -> a -> <br />
<br />
instance Num a => Num (Array a) where ..<br />
<br />
-- All indexing is 0-based (Dijkstra)<br />
</hasekll><br />
<br />
Basic operations<br />
<haskell><br />
-- A rank-0 array contains one item<br />
zilde :: Vector a -- Empty vector, rank 1<br />
enclose :: a -> Scalar a -- Returns a rank 0 array, of<br />
-- depth one greater than input<br />
<br />
encloseA :: Nat -- r<br />
-> Array a -- Rank n<br />
-> Array (Array a) -- Outer rank r, inner rank n-r<br />
-- encloseA 2 (Array [3,1,4]) : Array [3] (Array [1,4])<br />
-- enclose a = encloseA 0 (when a is an array)<br />
<br />
disclose :: Scalar a -> Array a<br />
discloseA :: Array (Array a) -> Array a<br />
<br />
iota :: Nat -> Array Nat -- iota n = [0 1 2 3 ... n-1]<br />
<br />
ravel :: Array a -> Vector a -- Flattens an array of arbitrary rank<br />
-- (including zero!) in row-major order<br />
-- Does not change depth<br />
<br />
reshape :: Vector Nat -- s: the shape<br />
-> Array a -- Arbitrary shape <br />
-> Array a -- Shape of result = s<br />
-- NB: ravel a = product (shape a) `reshape` a<br />
<br />
product :: Num a => a -> Array a -> Array a<br />
productA :: Num a => Axis -> a -> Array a -> Array a<br />
-- Result has rank one smaller than input<br />
<br />
shape :: Array a -> Vector Nat<br />
-- shape [[1 3] [5 2] [3 9]] = [3 2]<br />
-- shape [3 2] = [2] <br />
-- shape [2] = [1] <br />
<br />
-- rank = shape . shape -- Rank 1 and shape [1] <br />
-- Or we could have rank :: Array a -> Nat<br />
</haskell><br />
<br />
Swapping rank and depth<br />
<haskell><br />
rankOperator :: <br />
-- This is in J and it is somehow lovely in a way <br />
-- that ordinary mortals cannot understand<br />
-- rankOp 1 (+) A B<br />
<br />
-- Swapping rank and depth<br />
-- Array [2,4,5,3] Float <br />
-- --> Array [2,5] (Array [4,3] Float)<br />
-- And the reverse!<br />
<br />
rankOp rank-spec f = reshape rank-spec . f . unreshape rank-spec<br />
<br />
<br />
transpose :: Vector Nat -- Permutation of (iota (rank arg))<br />
-> Array a -- Arg<br />
-> Array a<br />
-- Permutes the axes <br />
</haskell><br />
<br />
More operations<br />
<haskell><br />
class Item a wher<br />
depth :: a -> Nat<br />
<br />
instance Item Float where<br />
depth _ = 0<br />
instance Item a => Item (Array a) where<br />
depth _ = 1 + depth (undefined :: a)<br />
<br />
<br />
catenate :: Array a -> Array a -> Array a<br />
-- Concatenates on last axis (or first in J)<br />
-- Checks for shape compatibility<br />
catenateA :: Axis -> Array a -> Array a -> Array a<br />
-- You can specify the axis<br />
<br />
-- Swapping rank with depth<br />
flatten :: Vector (Vector a) -> Array a<br />
<br />
vector :: [a] -> Vector a<br />
<br />
each :: (a -> b) -> Array a -> Array b<br />
<br />
simpleIndex -- m [a;b]<br />
:: Array a -- a: The array to index<br />
-> Vector (Array Nat) -- i: Outer array is a tuple<br />
-- of length = rank a<br />
-> Array a -- shape result = shape i[0] x shape i[1] ....<br />
simpleIndex a is = chooseIndex a (disclose (reduce (outer catenate) zilde is)) <br />
-- We aren't quite sure about this definition<br />
<br />
reduce :: (Array a -> Array a -> Array a) -> Array a<br />
-- All rank one smaller than input<br />
-> Array a -- Input<br />
-> Array a -- Rank one smaller than input<br />
-- except that rank 0 input gives identity<br />
<br />
reduceA :: Axis -> (a -> a -> a) -> a<br />
-> Array a<br />
-> Array a -- Rank one smaller than ieput<br />
<br />
<br />
outer :: (a -> b -> c) -- Function argument<br />
-> Array a -> Array b -- Two array arguments, arg1, arg2<br />
-> Array c -- Shape result = shape arg1 ++ shape arg2<br />
<br />
-- simpleIndex a (vector [enclose 3, enclose 4]) :: Array a (rank 0)<br />
-- mat [3 ; 4]<br />
<br />
chooseIndex -- m [b]<br />
:: Array a -- a: The array to index<br />
-> Array (Vector Nat) -- i: Inner arrays are the index tuples<br />
-- of length = rank a<br />
-> Array a -- shape result = shape i<br />
</haskell><br />
<br />
Various monomorphic pick operators<br />
<haskell><br />
pick1 :: Vector (Matrix (Vector a))<br />
-> Array (Nat, (Nat,Nat), Nat)<br />
-> Array a<br />
<br />
pick2 :: Vector (Matrix a)<br />
-> Array (Nat, (Nat,Nat))<br />
-> Array a<br />
<br />
-- Just an instance of pick2<br />
pick2 :: Vector (Matrix (Vector a))<br />
-> Array (Nat, (Nat,Nat))<br />
-> Array (Vector a)<br />
</haskell><br />
<br />
= Reference implementation =<br />
<br />
This implementation of the above API is intended to give its semantics.<br />
It is not intended to run fast!<br />
<br />
<haskell><br />
data Array a = Arr Shape [a]<br />
<br />
type Shape = [Nat]<br />
-- Invariant: Arr s xs: product s = length xs<br />
<br />
ravel :: Array a -> Vector a<br />
ravel (Arr s a) = Arr [product s] a<br />
<br />
zilde :: Vector a -- Empty vector, rank 1<br />
zilde = Arr [0] []<br />
<br />
enclose :: a -> Scalar a -- Returns a rank 0 array, of<br />
-- depth one greater than input<br />
enclose x = Arr [] [x]<br />
<br />
disclose :: Scalar a -> a <br />
disclose (Arr [] [x]) = x<br />
<br />
discloseA (Arr outer items)<br />
= Arr (outer ++ inner) [ i | Arr _ is <- items, i <- is ] <br />
where<br />
(Arr inner _ : _) = items<br />
<br />
<br />
transpose :: Vector Nat -- Permutation of (iota (rank arg))<br />
-> Array a -- Arg<br />
-> Array a<br />
transpose (Arr [n] perm) (Arr shape items)<br />
= assert (n == length shape ) $<br />
Arr (permute perm shape) <br />
(scramble ... items)<br />
<br />
-- Property: disclose (enclose x) == x<br />
<br />
shape :: Array a -> Vector Nat<br />
shape (Arr s a) = Arr [1] s<br />
<br />
reshape :: Vector Nat -- s: the shape<br />
-> Array a -- Arbitrary shape <br />
-> Array a -- Shape of result = s<br />
reshape (Arr [n] s) (Arr s' elts)<br />
| null elts = error "Reshape on empty array"<br />
| otherwise<br />
= Arr s (take (product s) (cycle elts))<br />
<br />
each :: (a -> b) -> Array a -> Array b<br />
each f (Arr s xs) = Arr s (map f xs)<br />
<br />
reduce :: (Array a -> Array a -> Array a) -> Array a<br />
-- All rank one smaller than input<br />
-> Array a -- Input<br />
-> Array a -- Rank one smaller than input<br />
-- except that rank 0 input gives identity<br />
reduce k z (Arr [] [item])<br />
= Arr [] [item] -- Identity on rank 0<br />
reduce k z (Arr (s:ss) items)<br />
= foldr k z (chop ss items)<br />
<br />
encloseA :: Nat -> Array a -> Array a<br />
encloseA n (Arr shape items)<br />
= Arr outer_shape (chop inner_shape items)<br />
where<br />
(outer_shape, inner_shape) = splitAt n shape<br />
<br />
chop :: Shape -> [item] -> [Array item]<br />
chop s [] = []<br />
chop s is = Arr s i : chop s is'<br />
where<br />
(i,is') = splitAt (product s) is<br />
</haskell><br />
<br />
== A couple of examples == <br />
<br />
<tt><br />
x = 0 1 2 : Array Float = Arr [2,3] [0,1,2,3,4,5]<br />
3 4 5 <br />
<br />
enclose x :: Array (Array Float)<br />
= Arr [] [Arr [2,3] [0,1,2,3,4,5]]<br />
</tt></div>Simonpjhttps://wiki.haskell.org/index.php?title=APL&diff=44791APL2012-03-08T10:26:22Z<p>Simonpj: New page: = An APL library for Haskell = APL is an array language with a highly-functional flavour, and a rich set of carefully-thought-out array operations. It would be interesting to build a Has...</p>
<hr />
<div>= An APL library for Haskell =<br />
<br />
APL is an array language with a highly-functional flavour, and a rich set of carefully-thought-out array operations. It would be interesting to build a Haskell library that offered a Haskell rendering of APL's array algebra, possibly (though not definitely) bound to a mature implementation.<br />
<br />
This page collects thoughts loosely based around that idea.</div>Simonpjhttps://wiki.haskell.org/index.php?title=Template_Haskell&diff=42717Template Haskell2011-11-03T09:21:18Z<p>Simonpj: /* Other useful resources */</p>
<hr />
<div>'''[http://hackage.haskell.org/package/template-haskell Template Haskell]''' is a [[GHC]] extension to Haskell that adds compile-time metaprogramming facilities. The original design can be found here: http://research.microsoft.com/~simonpj/papers/meta-haskell/ . It is [http://haskell.cs.yale.edu/ghc/docs/6.2/html/users_guide/template-haskell.html included] in GHC version 6. <br />
<br />
This page hopes to be a more central and organized repository of TH related things.<br />
<br />
=What is Template Haskell?=<br />
Template Haskell is an extension to Haskell 98 that allows you to do type-safe compile-time meta-programming, with Haskell both as the manipulating language and the language being manipulated. <br />
<br />
Intuitively Template Haskell provides new language features that allow us to convert back and forth between concrete syntax, i.e. what you would type when you write normal Haskell code, and abstract syntax trees. These abstract syntax trees are represented using Haskell datatypes and, at compile time, they can be manipulated by Haskell code. This allows you to reify (convert from concrete syntax to an abstract syntax tree) some code, transform it and splice it back in (convert back again), or even to produce completely new code and splice that in, while the compiler is compiling your module. <br />
<br />
For email about Template Haskell, use the [http://haskell.org/mailman/listinfo/glasgow-haskell-users GHC users mailing list]. It's worth joining if you start to use TH.<br />
<br />
= Template Haskell specification =<br />
<br />
Template Haskell is only documented rather informally at the moment. Here are the main resources:<br />
<br />
* [http://www.haskell.org/ghc/docs/latest/html/users_guide/template-haskell.html The user manual section on Template Haskell]<br />
* [http://www.haskell.org/ghc/docs/latest/html/users_guide/template-haskell.html#th-quasiquotation The user manual section on quasi-quotation], which is closely related to Template Haskell.<br />
* [http://research.microsoft.com/~simonpj/papers/meta-haskell/ The original Template Haskell paper]<br />
* [http://research.microsoft.com/~simonpj/tmp/notes2.ps Notes on Template Haskell version 2], which describes changes since the original paper. Section 8 describes the difficulty with pattern splices, which are therefore not implemented.<br />
* [http://haskell.org/ghc/docs/7.0-latest/html/libraries/template-haskell-2.5.0.0/Language-Haskell-TH.html The Template Haskell API]<br />
<br />
= Template Haskell tutorials and papers =<br />
<br />
* Bulat's tutorials:<br />
** [http://docs.google.com/uc?id=0B4BgTwf_ng_TM2MxZjJjZjctMTQ0OS00YzcwLWE5N2QtMDI0YzE4NGUwZDM3 [formerly /bz/thdoc.htm]]<br />
** [http://docs.google.com/uc?id=0B4BgTwf_ng_TOGJkZjM4ZTUtNGY5My00ZThhLTllNDQtYzJjMWJiMzJhZjNj [formerly /bz/th3.htm]]<br />
<br />
: One reader said "These docs are *brilliant* ! Exactly what I need to get an understanding of TH."<br />
<br />
<small>(Note: These documents are from [http://www.archive.org the Wayback machine] because the originals disappeared. They're public documents on Google docs, which shouldn't require logging in. However, if you're asked to sign in to view them, you're running into a known Google bug. You can fix it by browsing to [http://www.google.com Google], presumably gaining a cookie in the process.)</small><br />
<br />
* Mark Snyder's Template Haskell chapter on the Software Generation and Configuration Report<br />
** http://nix.cs.uu.nl/dist/courses/sgc-report-unstable-latest/manual/chunk-chapter/templatehaskell.html<br />
<br />
* A very short tutorial to understand the basics in 10 Minutes.<br />
** http://www.hyperedsoftware.com/blog/entries/first-stab-th.html<br />
<br />
* GHC Template Haskell documentation<br />
** http://www.haskell.org/ghc/docs/7.0.2/html/users_guide/template-haskell.html<br />
<br />
* Papers about Template Haskell<br />
<br />
** Template metaprogramming for Haskell, by Tim Sheard and Simon Peyton Jones, Oct 2002. [[http://haskell.org/wikiupload/c/ca/Meta-haskell.ps ps]]<br />
** Template Haskell: A Report From The Field, by Ian Lynagh, May 2003. [[http://haskell.org/wikiupload/2/24/Template_Haskell-A_Report_From_The_Field.ps ps]]<br />
** Unrolling and Simplifying Expressions with Template Haskell, by Ian Lynagh, December 2002. [[http://haskell.org/wikiupload/e/ed/Template-Haskell-Utils.ps ps]]<br />
** Automatic skeletons in Template Haskell, by Kevin Hammond, Jost Berthold and Rita Loogen, June 2003. [[http://haskell.org/wikiupload/6/69/AutoSkelPPL03.pdf pdf]]<br />
** Optimising Embedded DSLs using Template Haskell, by Sean Seefried, Manuel Chakravarty, Gabriele Keller, March 2004. [[http://haskell.org/wikiupload/b/b5/Seefried04th-pan.pdf pdf]]<br />
** Typing Template Haskell: Soft Types, by Ian Lynagh, August 2004. [[http://haskell.org/wikiupload/7/72/Typing_Template_Haskell_Soft_Types.ps ps]]<br />
<br />
= Other useful resources =<br />
<br />
* (2011) David Weber's [http://www.yesodweb.com/blog/2011/10/code-generation-conversation blog post on Template Haskell and quasi-quoting] in the context of Yesod.<br />
* [http://www.haskell.org/th/ The old Template Haskell web page]. Would someone feel like moving this material into the HaskellWiki?<br />
* Old and probably not too useful for most but maybe... http://www.cse.unsw.edu.au/~chak/haskell/ghc/comm/exts/th.html<br />
*[http://web.comlab.ox.ac.uk/oucl/work/ian.lynagh/Fraskell/ Fraskell documentation] & explanation of how Template Haskell is used to vastly speed it up.<br />
*[[Quasiquotation]]<br />
Feel free to update our Wikipedia entry<br />
http://en.wikipedia.org/wiki/Template_Haskell<br />
<br />
= Projects =<br />
<br />
What are you doing/planning to do/have done with Template Haskell?<br />
<br />
* The [http://www.ict.kth.se/org/ict/ecs/sam/projects/forsyde/www ForSyDe methodology] is currently implemented as a Haskell-based DSL which makes extensive use of Template Haskell.<br />
<br />
* I have written a primitive (untyped) binding to the Objective-C runtime system on Mac OS X. It needs just TH, no "stub files" are created, no seperate utilities are required. Initial snapshot is at http://www.kfunigraz.ac.at/imawww/thaller/wolfgang/HOC020103.tar.bz2 -- WolfgangThaller<br />
<br />
* I am writing Template Greencard - a reimplementation of GreenCard using TH. Many bits work out really nicely. A few bits didn't work so nicely - once I get some time to think, I'll try to persuade the TH folk to make some changes to fix some of these. -- AlastairReid<br />
<br />
* I'm writing Hacanon - a framework for automatic generation of C++ bindings. Read "automated Template Greencard for C++" (-: Darcs repo: http://www.ScannedInAvian.org/repos/hacanon - You'll need gccxml (http://www.gccxml.org/) to compile the exmples. - 27 Dec Lemmih.<br />
<br />
* Following other FFI tools developers, I see some future for Template HSFFIG, especially when it comes to autogenerate peek and poke methods for structures defined in C; may be useful for implementation of certain network protocols such as X11 where layout of messages is provided as C structure/union declaration. - 16 Dec 2005 DimitryGolubovsky<br />
<br />
* I am using Template Haskell as a mechanism to get parsed, typechecked code into an Ajax based Haskell Equational Reasoning tool [[Haskell Equational Reasoning Assistant]], as well as simplify the specification of equational relationships between pieces of code. There was a quicktime movie of the tool being used on http://www.gill-warbington.com/home/andy/share/hera1.html - AndyGill <br />
<br />
* I am working on functional metaprogramming techniques to enhance programming reliability and productivity, by reusing much of the existing compiler technology. Template Haskell is especially interesting for me because it permits to check size information of structures by the compiler, provided this information is available at compile time. This approach is especially appropriate for hardware designs, where the structures are fixed before the circuit starts operating. See our metaprogramming web page at http://www.infosun.fmi.uni-passau.de/cl/metaprog/ -- ChristophHerrmann(http://www.cs.st-and.ac.uk/~ch)<br />
<br />
* I am using Template Haskell to do type safe database access. I initially [http://www.nabble.com/Using-Template-Haskell-to-make-type-safe-database-access-td17027286.html proposed this on haskell-cafe]. I connect to the database at compile-time and let the database do SQL parsing and type inference. The result from parsing and type inference is used to build a type safe database query which can executed at run-time. [[MetaHDBC | You can find the project page here]] -- [mailto:mads_lindstroem@yahoo.dk Mads Lindstrøm]<br />
<br />
= Utilities =<br />
<br />
Helper functions, debugging functions, or more involved code e.g. a monadic fold algebra for TH.Syntax.<br />
<br />
* http://www.haskell.org/pipermail/template-haskell/2003-September/000176.html<br />
<br />
= Known Bugs =<br />
<br />
Take a look at the [http://hackage.haskell.org/trac/ghc/query?status=new&status=assigned&status=reopened&component=Template+Haskell&order=priority open bugs against Template Haskell] on the GHC bug tracker.<br />
<br />
= Wish list =<br />
<br />
Things that Ian Lynagh (Igloo) mentioned in his paper ''Template Haskell: A Report From The Field'' in May 2003 (available [http://www.haskell.org/th/papers.html here]), by section:<br />
<br />
* Section 2 (curses)<br />
** The ability to splice names (into "foreign import" declarations, in particular)<br />
** The ability to add things to the export list from a splice(?)<br />
** The ability to use things defined at the toplevel of a module from splices in that same module (would require multi-stage compilation, as opposed to the current approach of expanding splices during typechecking)<br />
<br />
* Section 3 (deriving instances of classes)<br />
** <strike>First-class reification</strike> (the <hask>reify</hask> function)<br />
** A way to discover whether a data constructor was defined infix or prefix (which is necessary to derive instances for <hask>Read</hask> and <hask>Show</hask> as outlined in [http://www.haskell.org/onlinereport/derived.html The Haskell 98 Report: Specification of Derived Instances]) (if there is a way, [http://www-users.cs.york.ac.uk/~ndm/derive/ Derive] seems ignorant of it)<br />
** Type/context splicing (in <hask>instance</hask> headers in particular)<br />
<br />
* Section 4 (printf)<br />
** He says something to the effect that a pattern-matching form of the quotation brackets would be cool if it was expressive enough to be useful, but that this would be hard. (Don't expect this anytime soon.)<br />
<br />
* Section 5 (fraskell)<br />
** Type information for quoted code (so that simplification can be done safely even with overloaded operations, like, oh, <hask>(+)</hask>)<br />
<br />
* Section 6 (pan)<br />
** Type info again, and strictnes info too (this one seems a bit pie-in-the-sky...)<br />
<br />
(Please leave the implemented ones here, but crossed off.)<br />
<br />
Any other features that may be nice, and TH projects you'd want to see.<br />
<br />
* A TH tutorial (mainly a distillation and update of ''Template Meta-programming in Haskell'' at this point)<br />
* <strike>Write Haddock documentation for the Template Haskell library (http://hackage.haskell.org/trac/ghc/ticket/1576).</strike><br />
* Make `reify` on a class return a list of the instances of that class (http://www.haskell.org/pipermail/template-haskell/2005-December/000503.html). (See also [http://hackage.haskell.org/trac/ghc/ticket/1577 GHC ticket #1577].)<br />
* A set of simple examples on this wiki page<br />
* A TH T-shirt with new logo to wear at conferences<br />
* (Long-term) Unify Language.Haskell.Syntax with Language.Haskell.TH.Syntax so there's just one way to do things (http://hackage.haskell.org/package/haskell-src-meta does a one-way translation, for haskell-src-exts)<br />
<br />
---------------<br />
<br />
= Tips and Tricks =<br />
<br />
== What to do when you can't splice that there ==<br />
<br />
When you try to splice something into the middle of a template and find that you just can't, instead of getting frustrated about it, why not use the template to see what it would look like in longhand? <br />
<br />
First, an excerpt from a module of my own. I, by the way, am SamB.<br />
<haskell><br />
{-# OPTIONS_GHC -fglasgow-exts -fth #-}<br />
<br />
module MMixMemory where<br />
<br />
import Data.Int<br />
import Data.Word<br />
<br />
class (Integral int, Integral word)<br />
=> SignConversion int word | int -> word, word -> int where<br />
<br />
toSigned :: word -> int<br />
toSigned = fromIntegral<br />
toUnsigned :: int -> word<br />
toUnsigned = fromIntegral<br />
<br />
</haskell><br />
<br />
Say I want to find out what I need to do to splice in the types for an instance declaration for the SignConversion class, so that I can declare instances for Int8 with Word8 through Int64 with Word64. So, I start up good-ol' GHCi and do the following:<br />
<br />
<haskell><br />
$ ghci -fth -fglasgow-exts<br />
Prelude> :l MMixMemory<br />
*MMixMemory> :m +Language.Haskell.TH.Syntax<br />
*MMixMemory Language.Haskell.TH.Syntax> runQ [d| instance SignConversion Int Word where |] >>= print<br />
[InstanceD [] (AppT (AppT (ConT MMixMemory.SignConversion) (ConT GHC.Base.Int)) (ConT GHC.Word.Word)) []]<br />
</haskell><br />
<br />
== What can <tt>reify</tt> see? ==<br />
<br />
When you use <tt>reify</tt> to give you information about a <tt>Name</tt>, GHC will tell you what it knows. But sometimes it doesn't know stuff. In particular<br />
<br />
* '''Imported things'''. When you reify an imported function, type constructor, class, etc, from (say) module M, GHC runs off to the interface file <tt>M.hi</tt> in which it deposited all the info it learned when compiling M. However, if you compiled M without optimisation (ie <tt>-O0</tt>, the default), and without <tt>-XTemplateHaskell</tt>, GHC tries to put as little info in the interface file as possible. (This is a possibly-misguided attempt to keep interface files small.) In particular, it may dump only the name and kind of a data type into <tt>M.hi</tt>, but not its constructors.<br />
: Under these circumstances you may reify a data type but get back no information about its data constructors or fields. Solution: compile M with <br />
:* <tt>-O</tt>, or<br />
:* <tt>-fno-omit-interface-pragmas</tt> (implied by -O), or<br />
:* <tt>-XTemplateHaskell</tt>.<br />
<br />
* '''Function definitions'''. The <tt>VarI</tt> constructor of the <tt>Info</tt> type advertises that you might get back the source code for a function definition. In fact, GHC currently (7.4) <em>always</em> returns <tt>Nothing</tt> in this field. It's a bit awkward and no one has really needed it.<br />
<br />
== Why does <tt>runQ</tt> crash if I try to reify something? ==<br />
<br />
This program will fail with an error message when you run it:<br />
<haskell><br />
main = do info <- runQ (reify (mkName "Bool")) -- more hygenic is: (reify ''Bool)<br />
putStrLn (pprint info)<br />
</haskell><br />
Reason: <tt>reify</tt> consults the type environment, and that is not available at run-time. The type of <tt>reify</tt> is <br />
<haskell><br />
reify :: Quasi m => Q a -> m a<br />
</haskell><br />
The IO monad is a poor-man's instance of <tt>Quasi</tt>; it can allocate unique names and gather error messages, but it can't do <tt>reify</tt>. This error should really be caught statically.<br />
<br />
Instead, you can run the splice directly (ex. in ghci -XTemplateHaskell), as the following shows:<br />
<br />
<haskell><br />
GHCi> let tup = $(tupE $ take 4 $ cycle [ [| "hi" |] , [| 5 |] ])<br />
GHCi> :type tup<br />
tup :: ([Char], Integer, [Char], Integer)<br />
<br />
GHCi> tup<br />
("hi",5,"hi",5)<br />
<br />
GHCi> $(stringE . show =<< reify ''Int)<br />
"TyConI (DataD [] GHC.Types.Int [] [NormalC GHC.Types.I# [(NotStrict,ConT GHC.Prim.Int#)]] [])"<br />
</haskell><br />
<br />
Here's an [http://www.haskell.org/pipermail/glasgow-haskell-users/2006-August/010844.html email thread with more details].<br />
<br />
-----------------<br />
<br />
= Examples =<br />
== Tuples ==<br />
=== Select from a tuple ===<br />
<br />
An example to select an element from a tuple of arbitrary size. Taken from [http://www.haskell.org/th/papers/meta-haskell.ps this paper].<br />
<br />
Use like so:<br />
<br />
> $(sel 2 3) ('a','b','c')<br />
'b'<br />
> $(sel 3 4) ('a','b','c','d')<br />
'c'<br />
<br />
<br />
<haskell><br />
sel :: Int -> Int -> ExpQ<br />
sel i n = [| \x -> $(caseE [| x |] [alt]) |]<br />
where alt :: MatchQ<br />
alt = match pat (normalB rhs) []<br />
<br />
pat :: Pat<br />
pat = tupP (map varP as)<br />
<br />
rhs :: ExpQ<br />
rhs = varE(as !! (i -1)) -- !! is 0 based<br />
<br />
as :: [String]<br />
as = ["a" ++ show i | i <- [1..n] ]<br />
</haskell><br />
<br />
Alternately:<br />
<br />
<haskell><br />
sel' i n = lamE [pat] rhs<br />
where pat = tupP (map varP as)<br />
rhs = varE (as !! (i - 1))<br />
as = [ "a" ++ show j | j <- [1..n] ]<br />
</haskell><br />
<br />
=== Apply a function to the n'th element ===<br />
<br />
<haskell><br />
tmap i n = do<br />
f <- newName "f"<br />
as <- replicateM n (newName "a")<br />
lamE [varP f, tupP (map varP as)] $<br />
tupE [ if i == i'<br />
then [| $(varE f) $a |]<br />
else a<br />
| (a,i') <- map varE as `zip` [1..] ]<br />
</haskell><br />
<br />
Then tmap can be called as:<br />
<br />
> $(tmap 3 4) (+ 1) (1,2,3,4)<br />
(1,2,4,4)<br />
<br />
=== Convert the first n elements of a list to a tuple ===<br />
<br />
This example creates a tuple by extracting elemnts from a list. Taken from<br />
[http://www.xoltar.org/2003/aug/13/templateHaskellTupleSample.html www.xoltar.org]<br />
<br />
Use like so:<br />
<br />
> $(tuple 3) [1,2,3,4,5]<br />
(1,2,3)<br />
> $(tuple 2) [1,2]<br />
(1,2)<br />
<br />
<haskell><br />
tuple :: Int -> ExpQ<br />
tuple n = [|\list -> $(tupE (exprs [|list|])) |]<br />
where<br />
exprs list = [infixE (Just (list))<br />
(varE "!!")<br />
(Just (litE $ integerL (toInteger num)))<br />
| num <- [0..(n - 1)]]<br />
</haskell><br />
<br />
An alternative that has more informative errors (a failing pattern match failures give an exact location):<br />
<br />
<haskell><br />
tuple :: Int -> ExpQ<br />
tuple n = do<br />
ns <- replicateM n (newName "x")<br />
lamE [foldr (\x y -> conP '(:) [varP x,y]) wildP ns] (tupE $ map varE ns)<br />
</haskell><br />
<br />
=== Un-nest tuples ===<br />
Convert nested tuples like (a,(b,(c,()))) into (a,b,c) given the length to generate.<br />
<br />
<haskell><br />
unNest n = do<br />
vs <- replicateM n (newName "x")<br />
lamE [foldr (\a b -> tupP [varP a , b])<br />
(conP '() [])<br />
vs]<br />
(tupE (map varE vs))<br />
</haskell><br />
<br />
<br />
<br />
== [[Template Haskell/Marshall Data|Marshall a datatype to and from Dynamic]] ==<br />
This approach is an example of using template haskell to delay typechecking<br />
to be able to abstract out the repeated calls to fromDynamic:<br />
<br />
<haskell><br />
data T = T Int String Double<br />
<br />
toT :: [Dynamic] -> Maybe T<br />
toT [a,b,c] = do<br />
a' <- fromDynamic a<br />
b' <- fromDynamic b<br />
c' <- fromDynamic c<br />
return (T a' b' c')<br />
toT _ = Nothing<br />
</haskell><br />
<br />
== Printf ==<br />
Build it using a command similar to:<br />
<br />
ghc --make Main.hs -o main<br />
<br />
Main.hs:<br />
<br />
<haskell><br />
{-# LANGUAGE TemplateHaskell #-}<br />
<br />
-- Import our template "printf"<br />
import PrintF (printf)<br />
<br />
-- The splice operator $ takes the Haskell source code<br />
-- generated at compile time by "printf" and splices it into<br />
-- the argument of "putStrLn".<br />
main = do<br />
putStrLn $ $(printf "Hello %s %%x%% %d %%x%%") "World" 12<br />
</haskell><br />
<br />
PrintF.hs:<br />
<br />
<haskell><br />
{-# LANGUAGE TemplateHaskell #-}<br />
module PrintF where<br />
<br />
-- NB: printf needs to be in a separate module to the one where<br />
-- you intend to use it.<br />
<br />
-- Import some Template Haskell syntax<br />
import Language.Haskell.TH<br />
<br />
-- Possible string tokens: %d %s and literal strings<br />
data Format = D | S | L String<br />
deriving Show<br />
<br />
-- a poor man's tokenizer<br />
tokenize :: String -> [Format]<br />
tokenize [] = []<br />
tokenize ('%':c:rest) | c == 'd' = D : tokenize rest<br />
| c == 's' = S : tokenize rest<br />
tokenize (s:str) = L (s:p) : tokenize rest -- so we don't get stuck on weird '%'<br />
where (p,rest) = span (/= '%') str<br />
<br />
-- generate argument list for the function<br />
args :: [Format] -> [PatQ]<br />
args fmt = concatMap (\(f,n) -> case f of<br />
L _ -> []<br />
_ -> [varP n]) $ zip fmt names<br />
where names = [ mkName $ 'x' : show i | i <- [0..] ]<br />
<br />
-- generate body of the function<br />
body :: [Format] -> ExpQ<br />
body fmt = foldr (\ e e' -> infixApp e [| (++) |] e') (last exps) (init exps)<br />
where exps = [ case f of<br />
L s -> stringE s<br />
D -> appE [| show |] (varE n)<br />
S -> varE n<br />
| (f,n) <- zip fmt names ]<br />
names = [ mkName $ 'x' : show i | i <- [0..] ]<br />
<br />
-- glue the argument list and body together into a lambda<br />
-- this is what gets spliced into the haskell code at the call<br />
-- site of "printf"<br />
printf :: String -> Q Exp<br />
printf format = lamE (args fmt) (body fmt)<br />
where fmt = tokenize format<br />
</haskell><br />
<br />
== Handling Options with Templates ==<br />
A common idiom for treating a set of options, e.g. from GetOpt, is to define a datatype with all the flags and using a list over this datatype:<br />
<br />
<haskell><br />
data Options = B1 | B2 | V Integer<br />
<br />
options = [B1, V 3]<br />
</haskell><br />
<br />
While it's simple testing if a Boolean flag is set (simply use "elem"), it's harder to check if an option with an argument is set. It's even more tedious writing helper-functions to obtain the value from such an option since you have to explicitely "un-V" each. Here, Template Haskell can be (ab)used to reduce this a bit. The following example provides the module "OptionsTH" which can be reused regardless of the constructors in "Options". Let's start with showing how we'd like to be able to program. Notice that the resulting lists need some more treatment e.g. through "foldl".<br />
<br />
Options.hs:<br />
<br />
<haskell><br />
module Main where<br />
<br />
import OptionsTH<br />
import Language.Haskell.TH.Syntax<br />
<br />
data Options = B1 | B2 | V Int | S String deriving (Eq, Read, Show)<br />
<br />
options = [B1, V 3]<br />
<br />
main = do<br />
print foo -- test if B1 set: [True,False]<br />
print bar -- test if V present, w/o value: [False,True]<br />
print baz -- get value of V if available: [Nothing,Just 3]<br />
<br />
foo :: [Bool]<br />
-- Query constructor B1 which takes no arguments<br />
foo = map $(getopt (THNoArg (mkArg "B1" 0))) options<br />
<br />
bar :: [Bool]<br />
-- V is a unary constructor. Let mkArg generate the required<br />
-- wildcard-pattern "V _".<br />
bar = map $(getopt (THNoArg (mkArg "V" 1))) options<br />
<br />
-- Can't use a wildcard here!<br />
baz :: [(Maybe Int)]<br />
baz = map $(getopt (THArg (conP "V" [varP "x"]))) options<br />
</haskell><br />
<br />
OptionsTH.hs<br />
<br />
<haskell><br />
module OptionsTH where<br />
<br />
import Language.Haskell.TH.Syntax<br />
<br />
-- datatype for querying options:<br />
-- NoArg: Not interested in value (also applies to Boolean flags)<br />
-- Arg: Grep value of unary(!) constructor<br />
data Args = THNoArg Pat | THArg Pat<br />
<br />
getopt :: Args -> ExpQ<br />
getopt (THNoArg pat) = lamE [varP "y"] (caseE (varE "y") [cons0, cons1])<br />
where<br />
cons0 = match pat (normalB [| True |]) []<br />
cons1 = match wildP (normalB [| False |]) []<br />
<br />
-- bind "var" for later use!<br />
getopt (THArg pat@(ConP _ [VarP var])) = lamE [varP "y"] (caseE (varE "y") [cons0, cons1])<br />
where<br />
cons0 = match pat (normalB (appE [|Just|] (varE var))) []<br />
cons1 = match wildP (normalB [|Nothing|]) []<br />
<br />
mkArg :: String -> Int -> Pat<br />
mkArg k c = conP k (replicate c wildP)<br />
</haskell><br />
<br />
While the example might look contrived for the Boolean options which could have been tested much easier, it shows how both types of arguments can be treated in a similar way.<br />
<br />
=== Limitations ===<br />
<tt>getopt (THArg pat)</tt> is only able to treat unary constructors. See the pattern-binding: It matches exactly a single VarP.<br />
<br />
=== Improvements ===<br />
The following reduces things even a bit more, though I still don't know if I like it. It only works since <tt>c</tt> is either 0 or 1.<br />
<br />
<haskell><br />
mkArg k c = conP k (replicate c (varP "x"))<br />
<br />
baz = map $(getopt (THArg (mkArg "V" 1)))<br />
</haskell><br />
-- VolkerStolz<br />
<br />
== Generic constructor for records ==<br />
<br />
I have a large number of record types like this, of different length:<br />
<br />
<haskell><br />
data PGD = PGD {<br />
pgdXUnitBase :: !Word8,<br />
pgdYUnitBase :: !Word8,<br />
pgdXLUnitsperUnitBase :: !Word16<br />
}<br />
</haskell><br />
<br />
Currently I use GHC's Binary module to read them from files; it can handle<br />
types like <tt>(Word8, (Word8, Word16))</tt>, but there was no easy way to generate<br />
the correct amount of "uncurry" calls for automatically grabbing each element.<br />
<br />
With Template Haskell, the instance declarations are now written as such:<br />
<br />
<haskell><br />
instance Binary PGD where<br />
get bh = do a <- get bh ; return $ $(constrRecord PGD) a<br />
</haskell><br />
<br />
Here the trick lies in constrRecord, which is defined as:<br />
<br />
<haskell><br />
constrRecord x = reify exp where<br />
reify = \(Just r) -> appE r $ conE $ last args<br />
exp = foldl (dot) uncur $ replicate terms uncur<br />
terms = ((length args) `div` 2) - 2<br />
dot x y = (Just $ infixE x (varE ".") y)<br />
uncur = (Just [|uncurry|])<br />
args = words . show $ typeOf x<br />
</haskell><br />
<br />
-- AutrijusTang<br />
<br />
== zipWithN ==<br />
<br />
Here $(zipn 3) = zipWith3 etc.<br />
<br />
<haskell><br />
import Language.Haskell.TH; import Control.Applicative; import Control.Monad<br />
<br />
zipn n = do<br />
vs <- replicateM n (newName "vs")<br />
[| \f -><br />
$(lamE (map varP vs)<br />
[| getZipList $<br />
$(foldl<br />
(\a b -> [| $a <*> $b |])<br />
[| pure f |]<br />
(map (\v -> [| ZipList $(varE v) |]) vs))<br />
|])<br />
|]<br />
</haskell><br />
<br />
== 'generic' zipWith ==<br />
A generalization of zipWith to almost any data. Demonstrates the ability to do dynamic binding with TH splices (note 'dyn').<br />
<br />
<haskell><br />
zipCons :: Name -> Int -> [String] -> ExpQ<br />
zipCons tyName ways functions = do<br />
let countFields :: Con -> (Name,Int)<br />
countFields x = case x of<br />
NormalC n (length -> fields) -> (n, fields)<br />
RecC n (length -> fields) -> (n,fields)<br />
InfixC _ n _ -> (n,2)<br />
ForallC _ _ ct -> countFields ct<br />
<br />
TyConI (DataD _ _ _ [countFields -> (c,n)] _) <- reify tyName<br />
when (n /= length functions) $ fail "wrong number of functions named"<br />
vs <- replicateM ways $ replicateM n $ newName "x"<br />
lamE (map (conP c . map varP) vs) $<br />
foldl (\con (vs,f) -><br />
con `appE`<br />
foldl appE<br />
(dyn f)<br />
(map varE vs))<br />
(conE c)<br />
(transpose vs `zip` functions)<br />
</haskell><br />
<br />
This example uses whichever '+' is in scope when the expression is spliced:<br />
<br />
<haskell><br />
:type $(zipCons ''(,,,) 2 (replicate 4 "+"))<br />
<br />
$(zipCons ''(,,,) 2 (replicate 4 "+"))<br />
:: (Num t, Num t1, Num t2, Num t3) =><br />
(t, t1, t2, t3) -> (t, t1, t2, t3) -> (t, t1, t2, t3)<br />
</haskell><br />
<br />
==[[Template haskell/Instance deriving example|Instance deriving example]]==<br />
An example using a 'deriving function' to generate a method instance <br />
per constructor of a type. The deriving function provides the body of the<br />
method.<br />
<br />
Note that this example assumes that the functions of the class take a parameter that is the same type as instance is parameterized with. <br />
<br />
The message [http://www.haskell.org/pipermail/template-haskell/2006-August/000581.html email message] contains the full source ([http://www.iist.unu.edu/~vs/haskell/TH_render.hs extracted file]).<br />
<br />
== [[Quasiquotation|QuasiQuoters]] ==<br />
New in ghc-6.10 is -XQuasiQuotes, which allows one to extend ghc's syntax from library code. Quite a few examples are given in [http://hackage.haskell.org/package/haskell-src-meta haskell-src-meta].<br />
<br />
=== Similarity with splices ===<br />
<br />
Quasiquoters used in expression contexts (those using the ''quoteExp'') behave to a first approximation like regular TH splices:<br />
<br />
<haskell><br />
simpleQQ = QuasiQuoter { quoteExp = stringE } -- in another module<br />
<br />
[$simpleQQ| a b c d |] == $(quoteExp simpleQQ " a b c d ")<br />
</haskell><br />
<br />
[[Category:Language extensions]]</div>Simonpjhttps://wiki.haskell.org/index.php?title=GHC/CloudAndHPCHaskell/Transport&diff=42409GHC/CloudAndHPCHaskell/Transport2011-10-11T12:38:22Z<p>Simonpj: /* HPC Network Interfaces */</p>
<hr />
<div>= Networking interfaces for Haskell =<br />
<br />
<br />
== Purpose of this page ==<br />
<br />
The purpose of this page is to collect information about networking interfaces to enable us to decide what would work best for Haskell in cloud and HPC applications.<br />
<br />
== Use cases ==<br />
<br />
The networking interface should address the following use cases:<br />
<br />
* Networked versions of DPH<br />
* CloudHaskell Networking<br />
* Client-Server development<br />
* Internet Services development<br />
<br />
<br />
== Existing C Networking API's ==<br />
<br />
=== IP ===<br />
<br />
The most well known network interfaces are those in the IP stack:<br />
* UPD - datagram delivery<br />
* TCP - sockets<br />
<br />
The IP interfaces have seen numerous enhancements in every programming language to provide further higher level interfaces, particularly for remote procedure calls (e.g. SUN RPC and Java RMI) and for the implementation of internet protocols (HTTP, imap). <br />
<br />
The maturity if IP is unmatched and quite possibly it's the only protocol suitable for offering services on the internet.<br />
<br />
=== HPC Network Interfaces ===<br />
<br />
HPC applications have typically been programmed for much higher performance hardware, such as Infiniband and numerous less well known one (Myrinet, Elan, Cray Seastar, IBM ...). All of these ship with one or more low level interfaces, which are generally distinct from IP interfaces in two areas:<br />
<br />
# there is extensive support for RDMA (remote DMA) transport, which follows the exchange of DMA handles among nodes, and results in 0-copy transport<br />
# completion of delivery is handled through the delivery of events, and applications either poll / spin on the appearance of an event or sleep on it.<br />
# there is minimal CPU involvement in the data transport, and typically user level applications may interface with the hardware directly.<br />
# the transport protocol is almost always message oriented, so re-assembly of complete messages as is common in TCP based applications is not needed.<br />
<br />
One way latencies of HPC networks are now in the range of 300ns to 5us, and bandwidths approach 10GB/sec.<br />
<br />
A number of higher level API's have been developed for HPC networking, but only in a few cases have more than a single hardware platform been addressed. Examples of these API's are:<br />
<br />
* The [https://www.openfabrics.org/index.php?option=com_content&view=article&id=3&Itemid=123 OFED] (Open Fabrics Alliance Stack). This is an extremely large networking stack with API's at many different levels which runs on all IB networks and on some ethernet interfaces. It's socket direct protocol (SDP) is most similar to TCP, yet has major performance degradation over low level API's such as the verbs API (VAPI). OFED is ''the'' stack for Infiniband, and works over raw Ethernet.<br />
* [http://www.cs.sandia.gov/Portals/ Portals.] Portals is a simple elegant API developed at Sandia with very rich delivery and event semantics. Portals was used (and forked) by the Lustre project (who call it LNET). LNET runs on some 10 different physical networks and can route between them. Designed to work with hardware support in the Network Interface Card. If that's not available, then latency is high.<br />
* [http://www.olcf.ornl.gov/center-projects/common-communication-interface/ CCI] - a light weight API also with a driver model. Very promising, excellent performance, and in early stages of design allowing for the incorporation of new features. Has a driver for UDP already. Very low latency, simple semantics.<br />
* [http://gasnet.cs.berkeley.edu/ Gasnet] - A transport API tuned to provide the PGAS features for UPC. Has many drivers. The GASNET website shows in its performance section how high the overhead of MPI can be in some cases. <br />
* [http://www.mcs.anl.gov/research/projects/mpi/ MPI] - really a large C programming interface for writing distributed parallel programs. It has many features outside networking and a rather involved communication group mechanism that (almost) precludes it from being used in environments where nodes come and go.<br />
<br />
'''Bottom line''': use CCI.<br />
<br />
== Requirements for different network applications ==<br />
<br />
* High Performance Computing<br />
** low latency<br />
** high throughput<br />
** one sided communication<br />
** possibility to leverage HW supported collectives and matching<br />
** support multiple networks<br />
** possible NOC and SOC implementations for communication with GPU's etc (see e.g. AMD FSA)<br />
** iov's<br />
* Cloud applications<br />
** XXX please assist here<br />
* Client Server development (e.g. a file service)<br />
** High throughput, medium low latency<br />
** Authentication<br />
** Routing with resilience<br />
** Channel bonding for load balancing and failover<br />
** Kernel and user level bindings<br />
** Secure remote DMA<br />
** Congestion control<br />
** iov's<br />
* Internet applications<br />
** large TCP connection counts<br />
** effective handling of DOS attacks</div>Simonpjhttps://wiki.haskell.org/index.php?title=GHC/CloudAndHPCHaskell/Transport&diff=42407GHC/CloudAndHPCHaskell/Transport2011-10-11T09:24:44Z<p>Simonpj: /* HPC Network Interfaces */</p>
<hr />
<div>= Networking interfaces for Haskell =<br />
<br />
<br />
== Purpose of this page ==<br />
<br />
The purpose of this page is to collect information about networking interfaces to enable us to decide what would work best for Haskell in cloud and HPC applications.<br />
<br />
== Use cases ==<br />
<br />
The networking interface should address the following use cases:<br />
<br />
* Networked versions of DPH<br />
* CloudHaskell Networking<br />
* Client-Server development<br />
* Internet Services development<br />
<br />
<br />
== Existing C Networking API's ==<br />
<br />
=== IP ===<br />
<br />
The most well known network interfaces are those in the IP stack:<br />
* UPD - datagram delivery<br />
* TCP - sockets<br />
<br />
The IP interfaces have seen numerous enhancements in every programming language to provide further higher level interfaces, particularly for remote procedure calls (e.g. SUN RPC and Java RMI) and for the implementation of internet protocols (HTTP, imap). <br />
<br />
The maturity if IP is unmatched and quite possibly it's the only protocol suitable for offering services on the internet.<br />
<br />
=== HPC Network Interfaces ===<br />
<br />
HPC applications have typically been programmed for much higher performance hardware, such as Infiniband and numerous less well known one (Myrinet, Elan, Cray Seastar, IBM ...). All of these ship with one or more low level interfaces, which are generally distinct from IP interfaces in two areas:<br />
<br />
# there is extensive support for RDMA (remote DMA) transport, which follows the exchange of DMA handles among nodes, and results in 0-copy transport<br />
# completion of delivery is handled through the delivery of events, and applications either poll / spin on the appearance of an event or sleep on it.<br />
# there is minimal CPU involvement in the data transport, and typically user level applications may interface with the hardware directly.<br />
# the transport protocol is almost always message oriented, so re-assembly of complete messages as is common in TCP based applications is not needed.<br />
<br />
One way latencies of HPC networks are now in the range of 300ns to 5us, and bandwidths approach 10GB/sec.<br />
<br />
A number of higher level API's have been developed for HPC networking, but only in a few cases have more than a single hardware platform been addressed. Examples of these API's are:<br />
<br />
* The [https://www.openfabrics.org/index.php?option=com_content&view=article&id=3&Itemid=123 OFED] (Open Fabrics Alliance Stack). This is an extremely large networking stack with API's at many different levels which runs on all IB networks and on some ethernet interfaces. It's socket direct protocol (SDP) is most similar to TCP, yet has major performance degradation over low level API's such as the verbs API (VAPI). OFED is ''the'' stack for Infiniband, and works over raw Ethernet.<br />
* [http://www.cs.sandia.gov/Portals/ Portals.] Portals is a simple elegant API developed at Sandia with very rich delivery and event semantics. Portals was used (and forked) by the Lustre project (who call it LNET). LNET runs on some 10 different physical networks and can route between them. Designed to work with hardware support in the Network Interface Card. If that's not available, then latency is high.<br />
* [http://www.olcf.ornl.gov/center-projects/common-communication-interface/ CCI] - a light weight API also with a driver model. Very promising, excellent performance, and in early stages of design allowing for the incorporation of new features. Has a driver for UDP already. Very low latency, simple semantics.<br />
* [http://gasnet.cs.berkeley.edu/ Gasnet] - A transport API tuned to provide the PGAS features for UPC. Has many drivers. The GASNET website shows in its performance section how high the overhead of MPI can be in some cases. <br />
* [http://www.mcs.anl.gov/research/projects/mpi/ MPI] - really a large C programming interface for writing distributed parallel programs. It has many features outside networking and a rather involved communication group mechanism that (almost) precludes it from being used in environments where nodes come and go.<br />
<br />
== Requirements for different network applications ==<br />
<br />
* High Performance Computing<br />
** low latency<br />
** high throughput<br />
** one sided communication<br />
** possibility to leverage HW supported collectives and matching<br />
** support multiple networks<br />
** possible NOC and SOC implementations for communication with GPU's etc (see e.g. AMD FSA)<br />
** iov's<br />
* Cloud applications<br />
** XXX please assist here<br />
* Client Server development (e.g. a file service)<br />
** High throughput, medium low latency<br />
** Authentication<br />
** Routing with resilience<br />
** Channel bonding for load balancing and failover<br />
** Kernel and user level bindings<br />
** Secure remote DMA<br />
** Congestion control<br />
** iov's<br />
* Internet applications<br />
** large TCP connection counts<br />
** effective handling of DOS attacks</div>Simonpjhttps://wiki.haskell.org/index.php?title=GHC/CloudAndHPCHaskell/Transport&diff=42406GHC/CloudAndHPCHaskell/Transport2011-10-11T09:22:25Z<p>Simonpj: /* HPC Network Interfaces */</p>
<hr />
<div>= Networking interfaces for Haskell =<br />
<br />
<br />
== Purpose of this page ==<br />
<br />
The purpose of this page is to collect information about networking interfaces to enable us to decide what would work best for Haskell in cloud and HPC applications.<br />
<br />
== Use cases ==<br />
<br />
The networking interface should address the following use cases:<br />
<br />
* Networked versions of DPH<br />
* CloudHaskell Networking<br />
* Client-Server development<br />
* Internet Services development<br />
<br />
<br />
== Existing C Networking API's ==<br />
<br />
=== IP ===<br />
<br />
The most well known network interfaces are those in the IP stack:<br />
* UPD - datagram delivery<br />
* TCP - sockets<br />
<br />
The IP interfaces have seen numerous enhancements in every programming language to provide further higher level interfaces, particularly for remote procedure calls (e.g. SUN RPC and Java RMI) and for the implementation of internet protocols (HTTP, imap). <br />
<br />
The maturity if IP is unmatched and quite possibly it's the only protocol suitable for offering services on the internet.<br />
<br />
=== HPC Network Interfaces ===<br />
<br />
HPC applications have typically been programmed for much higher performance hardware, such as Infiniband and numerous less well known one (Myrinet, Elan, Cray Seastar, IBM ...). All of these ship with one or more low level interfaces, which are generally distinct from IP interfaces in two areas:<br />
<br />
# there is extensive support for RDMA (remote DMA) transport, which follows the exchange of DMA handles among nodes, and results in 0-copy transport<br />
# completion of delivery is handled through the delivery of events, and applications either poll / spin on the appearance of an event or sleep on it.<br />
# there is minimal CPU involvement in the data transport, and typically user level applications may interface with the hardware directly.<br />
# the transport protocol is almost always message oriented, so re-assembly of complete messages as is common in TCP based applications is not needed.<br />
<br />
One way latencies of HPC networks are now in the range of 300ns to 5us, and bandwidths approach 10GB/sec.<br />
<br />
A number of higher level API's have been developed for HPC networking, but only in a few cases have more than a single hardware platform been addressed. Examples of these API's are:<br />
<br />
* The [https://www.openfabrics.org/index.php?option=com_content&view=article&id=3&Itemid=123 OFED] (Open Fabrics Alliance Stack). This is an extremely large networking stack with API's at many different levels which runs on all IB networks and on some ethernet interfaces. It's socket direct protocol (SDP) is most similar to TCP, yet has major performance degradation over low level API's such as the verbs API (VAPI). OFED is ''the'' stack for Infiniband, and works over raw Ethernet.<br />
* [http://www.cs.sandia.gov/Portals/ Portals.] Portals is a simple elegant API developed at Sandia with very rich delivery and event semantics. Portals was used (and forked) by the Lustre project (who call it LNET). LNET runs on some 10 different physical networks and can route between them.<br />
* [http://www.olcf.ornl.gov/center-projects/common-communication-interface/ CCI] - a light weight API also with a driver model. Very promising, excellent performance, and in early stages of design allowing for the incorporation of new features. Has a driver for UDP already.<br />
* [http://gasnet.cs.berkeley.edu/ Gasnet] - A transport API tuned to provide the PGAS features for UPC. Has many drivers. The GASNET website shows in its performance section how high the overhead of MPI can be in some cases. <br />
* [http://www.mcs.anl.gov/research/projects/mpi/ MPI] - really a large C programming interface for writing distributed parallel programs. It has many features outside networking and a rather involved communication group mechanism that (almost) precludes it from being used in environments where nodes come and go.<br />
<br />
== Requirements for different network applications ==<br />
<br />
* High Performance Computing<br />
** low latency<br />
** high throughput<br />
** one sided communication<br />
** possibility to leverage HW supported collectives and matching<br />
** support multiple networks<br />
** possible NOC and SOC implementations for communication with GPU's etc (see e.g. AMD FSA)<br />
** iov's<br />
* Cloud applications<br />
** XXX please assist here<br />
* Client Server development (e.g. a file service)<br />
** High throughput, medium low latency<br />
** Authentication<br />
** Routing with resilience<br />
** Channel bonding for load balancing and failover<br />
** Kernel and user level bindings<br />
** Secure remote DMA<br />
** Congestion control<br />
** iov's<br />
* Internet applications<br />
** large TCP connection counts<br />
** effective handling of DOS attacks</div>Simonpjhttps://wiki.haskell.org/index.php?title=GHC/CloudAndHPCHaskell/Transport&diff=42405GHC/CloudAndHPCHaskell/Transport2011-10-11T09:20:36Z<p>Simonpj: /* HPC Network Interfaces */</p>
<hr />
<div>= Networking interfaces for Haskell =<br />
<br />
<br />
== Purpose of this page ==<br />
<br />
The purpose of this page is to collect information about networking interfaces to enable us to decide what would work best for Haskell in cloud and HPC applications.<br />
<br />
== Use cases ==<br />
<br />
The networking interface should address the following use cases:<br />
<br />
* Networked versions of DPH<br />
* CloudHaskell Networking<br />
* Client-Server development<br />
* Internet Services development<br />
<br />
<br />
== Existing C Networking API's ==<br />
<br />
=== IP ===<br />
<br />
The most well known network interfaces are those in the IP stack:<br />
* UPD - datagram delivery<br />
* TCP - sockets<br />
<br />
The IP interfaces have seen numerous enhancements in every programming language to provide further higher level interfaces, particularly for remote procedure calls (e.g. SUN RPC and Java RMI) and for the implementation of internet protocols (HTTP, imap). <br />
<br />
The maturity if IP is unmatched and quite possibly it's the only protocol suitable for offering services on the internet.<br />
<br />
=== HPC Network Interfaces ===<br />
<br />
HPC applications have typically been programmed for much higher performance hardware, such as Infiniband and numerous less well known one (Myrinet, Elan, Cray Seastar, IBM ...). All of these ship with one or more low level interfaces, which are generally distinct from IP interfaces in two areas:<br />
<br />
# there is extensive support for RDMA (remote DMA) transport, which follows the exchange of DMA handles among nodes, and results in 0-copy transport<br />
# completion of delivery is handled through the delivery of events, and applications either poll / spin on the appearance of an event or sleep on it.<br />
# there is minimal CPU involvement in the data transport, and typically user level applications may interface with the hardware directly.<br />
# the transport protocol is almost always message oriented, so re-assembly of complete messages as is common in TCP based applications is not needed.<br />
<br />
One way latencies of HPC networks are now in the range of 300ns to 5us, and bandwidths approach 10GB/sec.<br />
<br />
A number of higher level API's have been developed for HPC networking, but only in a few cases have more than a single hardware platform been addressed. Examples of these API's are:<br />
<br />
* The [https://www.openfabrics.org/index.php?option=com_content&view=article&id=3&Itemid=123 OFED] (Open Fabrics Alliance Stack). This is an extremely large networking stack with API's at many different levels which runs on all IB networks and on some ethernet interfaces. It's socket direct protocol (SDP) is most similar to TCP, yet has major performance degradation over low level API's such as the verbs API (VAPI)<br />
* [http://www.cs.sandia.gov/Portals/ Portals.] Portals is a simple elegant API developed at Sandia with very rich delivery and event semantics. Portals was used (and forked) by the Lustre project (who call it LNET). LNET runs on some 10 different physical networks and can route between them.<br />
* [http://www.olcf.ornl.gov/center-projects/common-communication-interface/ CCI] - a light weight API also with a driver model. Very promising, excellent performance, and in early stages of design allowing for the incorporation of new features. Has a driver for UDP already.<br />
* [http://gasnet.cs.berkeley.edu/ Gasnet] - A transport API tuned to provide the PGAS features for UPC. Has many drivers. The GASNET website shows in its performance section how high the overhead of MPI can be in some cases. <br />
* [http://www.mcs.anl.gov/research/projects/mpi/ MPI] - really a large C programming interface for writing distributed parallel programs. It has many features outside networking and a rather involved communication group mechanism that (almost) precludes it from being used in environments where nodes come and go.<br />
<br />
== Requirements for different network applications ==<br />
<br />
* High Performance Computing<br />
** low latency<br />
** high throughput<br />
** one sided communication<br />
** possibility to leverage HW supported collectives and matching<br />
** support multiple networks<br />
** possible NOC and SOC implementations for communication with GPU's etc (see e.g. AMD FSA)<br />
** iov's<br />
* Cloud applications<br />
** XXX please assist here<br />
* Client Server development (e.g. a file service)<br />
** High throughput, medium low latency<br />
** Authentication<br />
** Routing with resilience<br />
** Channel bonding for load balancing and failover<br />
** Kernel and user level bindings<br />
** Secure remote DMA<br />
** Congestion control<br />
** iov's<br />
* Internet applications<br />
** large TCP connection counts<br />
** effective handling of DOS attacks</div>Simonpjhttps://wiki.haskell.org/index.php?title=GHC/CloudAndHPCHaskell&diff=42404GHC/CloudAndHPCHaskell2011-10-11T08:48:58Z<p>Simonpj: </p>
<hr />
<div>= Haskell in the Cloud =<br />
<br />
This page serves to discuss the architecture of Cloud and High Performance Computing (HPC) frameworks, possibly with an emphasis on the distributed execution and network model.<br />
<br />
Subpages: <br />
* http://haskell.org/haskellwiki/GHC/CloudAndHPCHaskell/Transport<br />
<br />
== Relevant papers ==<br />
* [http://research.microsoft.com/en-us/um/people/simonpj/papers/parallel/remote.pdf Towards Haskell in the Cloud], Jeff Epstein, Andrew Black, and Simon Peyton Jones, ICFP 2011<br />
<br />
== Peter Braam's thoughts about HPC & Cloud Compute Frameworks ==<br />
<br />
I want to describe here what is taking place in HPC and cloud computing, and how I think it could impact the architecture of the Haskell packages we are discussing. <br />
<br />
In HPC the 90's saw the emergence of clusters for computing with a distributed memory model. MPI became the de-facto standard for this some 10 years later. Then multicore entered the game for which OpenMP became the software and communication "standard", and more recently GPGPU's (which have CUDA and OpenCL) and other accelerators (FPGA boards are seeing a revival). Moreover, other many core chips which have a NOC (network on chip) are becoming important. It is likely that these hybrid architectures which are sometimes even re-configurable will remain prominent for the next 10 years or so.<br />
<br />
The HPC community is looking for a software platform to program these complex systems within one model - things like CUDA + OpenMP + MPI are way too complicated. The architecture of the system must be made a first class citizen in further considerations for that to succeed. The architecture should be some kind of data structure, influenced by the hardware industry, that describes the networks with their interfaces and topologies that connect nodes, and include the various kinds of memories present in the node, the CPU chips with cores and accelerators with their memories and NOC's. As an example of this interest, AMD is developing the so called FSA architecture that does this at least for a node. It provides very low level interfaces to the components for instruction / data / thread dispatch and scheduling. Elements of such architecture descriptions exist (e.g. LLNL "genders" and resources associated with schedulers), but nowhere close to what we need.<br />
<br />
A second key element is the scheduler. Until recently, things like HPC or the Hadoop job schedulers started jobs. Now, much more needs to be scheduled, on different cores, on accelerator boards and so on. The scheduler is responsible to create running entities on the components of the architecture, importantly these running entities normally read input data from a distributed file system or database. Currently scheduling is another messy story - one thing starts processes on remote nodes, another element spawns threads, and yet other facilities deal with the accelerators.<br />
<br />
The networks are increasingly complicated too. There are now facilities to send packets directly from CPU caches to Infiniband networks, and people are working to set up networking between the accelerators and the cluster network (often IB). Moreover, most of the architectures are NUMA now. There are API's (like CCI) that aim to unify these various transports as one. About MPI, one gets about 50% of the bandwidth that is available, it's not a good platform anymore (see http://gasnet.cs.berkeley.edu/ for comparison with a PGAS oriented transport - created for UPC, or see ETI's web pages about SWARM).<br />
<br />
Unlike client server jobs and unlike user applications running a 3rd party network protocols, the cloud and HPC jobs would probably be well served with an SPMD like model even with these complex architectures. I think that in SPMD models much communication is the exchange of memory, with just one caveat that sending small messages is very costly. With that we can hide the network almost completely from the programmer, just like DPH hides the cores.<br />
<br />
Combining DPH with (i) networking, (ii) a BSP (Bulk Synchronous Processing) mode (iii) and beginning to look at other dispatch after vectorizing in DPH (e.g. to Accelerate) - probably totally obvious ideas to you would provide the parallel programs the Architecture and Scheduler can run. Encapsulating network and node failures in some Monad should be possible, and would as mentioned be an important component, or hopefully a perpendicular extension. The OTP failure model is perfect for purely functional situations, but with state involved things like checkpoints and exactly once semantics make it more involved.<br />
<br />
This is in some sense just elaborating what SPJ said at a CUFP 2011 breakfast last week. I think that getting rid of compiler flags and runtime hints and instead leverage a built in scheduler / architecture model would be a good first step.</div>Simonpjhttps://wiki.haskell.org/index.php?title=GHC/CloudAndHPCHaskell&diff=42296GHC/CloudAndHPCHaskell2011-10-03T17:47:32Z<p>Simonpj: GHC/ClouldAndHPCHaskell moved to GHC/CloudAndHPCHaskell: Still mis-spelt</p>
<hr />
<div>This page serves to discuss the architecture of Cloud and HPC frameworks, possibly with an emphasis on the distributed execution and network model.<br />
<br />
Subpages: <br />
* http://haskell.org/haskellwiki/GHC/CloudAndHPCHaskell/Transport<br />
<br />
'''Peter Braam's thoughts about HPC & Cloud Compute Frameworks<br />
'''<br />
<br />
I want to describe here what is taking place in HPC and cloud computing, and how I think it could impact the architecture of the Haskell packages we are discussing. <br />
<br />
In HPC the 90's saw the emergence of clusters for computing with a distributed memory model. MPI became the de-facto standard for this some 10 years later. Then multicore entered the game for which OpenMP became the software and communication "standard", and more recently GPGPU's (which have CUDA and OpenCL) and other accelerators (FPGA boards are seeing a revival). Moreover, other many core chips which have a NOC (network on chip) are becoming important. It is likely that these hybrid architectures which are sometimes even re-configurable will remain prominent for the next 10 years or so.<br />
<br />
The HPC community is looking for a software platform to program these complex systems within one model - things like CUDA + OpenMP + MPI are way too complicated. The architecture of the system must be made a first class citizen in further considerations for that to succeed. The architecture should be some kind of data structure, influenced by the hardware industry, that describes the networks with their interfaces and topologies that connect nodes, and include the various kinds of memories present in the node, the CPU chips with cores and accelerators with their memories and NOC's. As an example of this interest, AMD is developing the so called FSA architecture that does this at least for a node. It provides very low level interfaces to the components for instruction / data / thread dispatch and scheduling. Elements of such architecture descriptions exist (e.g. LLNL "genders" and resources associated with schedulers), but nowhere close to what we need.<br />
<br />
A second key element is the scheduler. Until recently, things like HPC or the Hadoop job schedulers started jobs. Now, much more needs to be scheduled, on different cores, on accelerator boards and so on. The scheduler is responsible to create running entities on the components of the architecture, importantly these running entities normally read input data from a distributed file system or database. Currently scheduling is another messy story - one thing starts processes on remote nodes, another element spawns threads, and yet other facilities deal with the accelerators.<br />
<br />
The networks are increasingly complicated too. There are now facilities to send packets directly from registers to Infiniband networks, and people are working to set up networking between the accelerators and the cluster network (often IB). Moreover, most of the architectures are NUMA now. There are API's (like CCI) that aim to unify these various transports as one. About MPI, one gets about 50% of the bandwidth that is available, it's not a good platform anymore (see http://gasnet.cs.berkeley.edu/ for comparison with a PGAS oriented transport - created for UPC, or see ETI's web pages about SWARM).<br />
<br />
Unlike client server jobs and unlike user applications running a 3rd party network protocols, the cloud and HPC jobs would probably be well served with an SPMD like model even with these complex architectures. I think that in SPMD models much communication is the exchange of memory, with just one caveat that sending small messages is very costly. With that we can hide the network almost completely from the programmer, just like DPH hides the cores.<br />
<br />
Combining DPH with (i) networking, (ii) a BSP (Bulk Synchronous Processing) mode (iii) and beginning to look at other dispatch after vectorizing in DPH (e.g. to Accelerate) - probably totally obvious ideas to you would provide the parallel programs the Architecture and Scheduler can run. Encapsulating network and node failures in some Monad should be possible, and would as mentioned be an important component, or hopefully a perpendicular extension. The OTP failure model is perfect for purely functional situations, but with state involved things like checkpoints and exactly once semantics make it more involved.<br />
<br />
This is in some sense just elaborating what SPJ said at a CUFP 2011 breakfast last week. I think that getting rid of compiler flags and runtime hints and instead leverage a built in scheduler / architecture model would be a good first step.</div>Simonpjhttps://wiki.haskell.org/index.php?title=GHC/ClouldAndHPCHaskell&diff=42297GHC/ClouldAndHPCHaskell2011-10-03T17:47:32Z<p>Simonpj: GHC/ClouldAndHPCHaskell moved to GHC/CloudAndHPCHaskell: Still mis-spelt</p>
<hr />
<div>#REDIRECT [[GHC/CloudAndHPCHaskell]]</div>Simonpjhttps://wiki.haskell.org/index.php?title=GHC/CloudAndHPCHaskell&diff=42294GHC/CloudAndHPCHaskell2011-10-03T17:47:00Z<p>Simonpj: GHC/CouldAndHPCHaskell moved to GHC/ClouldAndHPCHaskell: Mis-spelt name</p>
<hr />
<div>This page serves to discuss the architecture of Cloud and HPC frameworks, possibly with an emphasis on the distributed execution and network model.<br />
<br />
Subpages: <br />
* http://haskell.org/haskellwiki/GHC/CloudAndHPCHaskell/Transport<br />
<br />
'''Peter Braam's thoughts about HPC & Cloud Compute Frameworks<br />
'''<br />
<br />
I want to describe here what is taking place in HPC and cloud computing, and how I think it could impact the architecture of the Haskell packages we are discussing. <br />
<br />
In HPC the 90's saw the emergence of clusters for computing with a distributed memory model. MPI became the de-facto standard for this some 10 years later. Then multicore entered the game for which OpenMP became the software and communication "standard", and more recently GPGPU's (which have CUDA and OpenCL) and other accelerators (FPGA boards are seeing a revival). Moreover, other many core chips which have a NOC (network on chip) are becoming important. It is likely that these hybrid architectures which are sometimes even re-configurable will remain prominent for the next 10 years or so.<br />
<br />
The HPC community is looking for a software platform to program these complex systems within one model - things like CUDA + OpenMP + MPI are way too complicated. The architecture of the system must be made a first class citizen in further considerations for that to succeed. The architecture should be some kind of data structure, influenced by the hardware industry, that describes the networks with their interfaces and topologies that connect nodes, and include the various kinds of memories present in the node, the CPU chips with cores and accelerators with their memories and NOC's. As an example of this interest, AMD is developing the so called FSA architecture that does this at least for a node. It provides very low level interfaces to the components for instruction / data / thread dispatch and scheduling. Elements of such architecture descriptions exist (e.g. LLNL "genders" and resources associated with schedulers), but nowhere close to what we need.<br />
<br />
A second key element is the scheduler. Until recently, things like HPC or the Hadoop job schedulers started jobs. Now, much more needs to be scheduled, on different cores, on accelerator boards and so on. The scheduler is responsible to create running entities on the components of the architecture, importantly these running entities normally read input data from a distributed file system or database. Currently scheduling is another messy story - one thing starts processes on remote nodes, another element spawns threads, and yet other facilities deal with the accelerators.<br />
<br />
The networks are increasingly complicated too. There are now facilities to send packets directly from registers to Infiniband networks, and people are working to set up networking between the accelerators and the cluster network (often IB). Moreover, most of the architectures are NUMA now. There are API's (like CCI) that aim to unify these various transports as one. About MPI, one gets about 50% of the bandwidth that is available, it's not a good platform anymore (see http://gasnet.cs.berkeley.edu/ for comparison with a PGAS oriented transport - created for UPC, or see ETI's web pages about SWARM).<br />
<br />
Unlike client server jobs and unlike user applications running a 3rd party network protocols, the cloud and HPC jobs would probably be well served with an SPMD like model even with these complex architectures. I think that in SPMD models much communication is the exchange of memory, with just one caveat that sending small messages is very costly. With that we can hide the network almost completely from the programmer, just like DPH hides the cores.<br />
<br />
Combining DPH with (i) networking, (ii) a BSP (Bulk Synchronous Processing) mode (iii) and beginning to look at other dispatch after vectorizing in DPH (e.g. to Accelerate) - probably totally obvious ideas to you would provide the parallel programs the Architecture and Scheduler can run. Encapsulating network and node failures in some Monad should be possible, and would as mentioned be an important component, or hopefully a perpendicular extension. The OTP failure model is perfect for purely functional situations, but with state involved things like checkpoints and exactly once semantics make it more involved.<br />
<br />
This is in some sense just elaborating what SPJ said at a CUFP 2011 breakfast last week. I think that getting rid of compiler flags and runtime hints and instead leverage a built in scheduler / architecture model would be a good first step.</div>Simonpjhttps://wiki.haskell.org/index.php?title=GHC/CouldAndHPCHaskell&diff=42295GHC/CouldAndHPCHaskell2011-10-03T17:47:00Z<p>Simonpj: GHC/CouldAndHPCHaskell moved to GHC/ClouldAndHPCHaskell: Mis-spelt name</p>
<hr />
<div>#REDIRECT [[GHC/ClouldAndHPCHaskell]]</div>Simonpjhttps://wiki.haskell.org/index.php?title=Template_Haskell&diff=41984Template Haskell2011-09-09T11:45:55Z<p>Simonpj: /* What can reify see? */</p>
<hr />
<div>'''[http://hackage.haskell.org/package/template-haskell Template Haskell]''' is a [[GHC]] extension to Haskell that adds compile-time metaprogramming facilities. The original design can be found here: http://research.microsoft.com/~simonpj/papers/meta-haskell/ . It is [http://haskell.cs.yale.edu/ghc/docs/6.2/html/users_guide/template-haskell.html included] in GHC version 6. <br />
<br />
This page hopes to be a more central and organized repository of TH related things.<br />
<br />
=What is Template Haskell?=<br />
Template Haskell is an extension to Haskell 98 that allows you to do type-safe compile-time meta-programming, with Haskell both as the manipulating language and the language being manipulated. <br />
<br />
Intuitively Template Haskell provides new language features that allow us to convert back and forth between concrete syntax, i.e. what you would type when you write normal Haskell code, and abstract syntax trees. These abstract syntax trees are represented using Haskell datatypes and, at compile time, they can be manipulated by Haskell code. This allows you to reify (convert from concrete syntax to an abstract syntax tree) some code, transform it and splice it back in (convert back again), or even to produce completely new code and splice that in, while the compiler is compiling your module. <br />
<br />
For email about Template Haskell, use the [http://haskell.org/mailman/listinfo/glasgow-haskell-users GHC users mailing list]. It's worth joining if you start to use TH.<br />
<br />
= Template Haskell specification =<br />
<br />
Template Haskell is only documented rather informally at the moment. Here are the main resources:<br />
<br />
* [http://www.haskell.org/ghc/docs/latest/html/users_guide/template-haskell.html The user manual section on Template Haskell]<br />
* [http://www.haskell.org/ghc/docs/latest/html/users_guide/template-haskell.html#th-quasiquotation The user manual section on quasi-quotation], which is closely related to Template Haskell.<br />
* [http://research.microsoft.com/~simonpj/papers/meta-haskell/ The original Template Haskell paper]<br />
* [http://research.microsoft.com/~simonpj/tmp/notes2.ps Notes on Template Haskell version 2], which describes changes since the original paper. Section 8 describes the difficulty with pattern splices, which are therefore not implemented.<br />
* [http://haskell.org/ghc/docs/7.0-latest/html/libraries/template-haskell-2.5.0.0/Language-Haskell-TH.html The Template Haskell API]<br />
<br />
= Template Haskell tutorials and papers =<br />
<br />
* Bulat's tutorials:<br />
** [http://docs.google.com/uc?id=0B4BgTwf_ng_TM2MxZjJjZjctMTQ0OS00YzcwLWE5N2QtMDI0YzE4NGUwZDM3 [formerly /bz/thdoc.htm]]<br />
** [http://docs.google.com/uc?id=0B4BgTwf_ng_TOGJkZjM4ZTUtNGY5My00ZThhLTllNDQtYzJjMWJiMzJhZjNj [formerly /bz/th3.htm]]<br />
<br />
: One reader said "These docs are *brilliant* ! Exactly what I need to get an understanding of TH."<br />
<br />
<small>(Note: These documents are from [http://www.archive.org the Wayback machine] because the originals disappeared. They're public documents on Google docs, which shouldn't require logging in. However, if you're asked to sign in to view them, you're running into a known Google bug. You can fix it by browsing to [http://www.google.com Google], presumably gaining a cookie in the process.)</small><br />
<br />
* Mark Snyder's Template Haskell chapter on the Software Generation and Configuration Report<br />
** http://nix.cs.uu.nl/dist/courses/sgc-report-unstable-latest/manual/chunk-chapter/templatehaskell.html<br />
<br />
* A very short tutorial to understand the basics in 10 Minutes.<br />
** http://www.hyperedsoftware.com/blog/entries/first-stab-th.html<br />
<br />
* GHC Template Haskell documentation<br />
** http://www.haskell.org/ghc/docs/7.0.2/html/users_guide/template-haskell.html<br />
<br />
* Papers about Template Haskell<br />
<br />
** Template metaprogramming for Haskell, by Tim Sheard and Simon Peyton Jones, Oct 2002. [[http://haskell.org/wikiupload/c/ca/Meta-haskell.ps ps]]<br />
** Template Haskell: A Report From The Field, by Ian Lynagh, May 2003. [[http://haskell.org/wikiupload/2/24/Template_Haskell-A_Report_From_The_Field.ps ps]]<br />
** Unrolling and Simplifying Expressions with Template Haskell, by Ian Lynagh, December 2002. [[http://haskell.org/wikiupload/e/ed/Template-Haskell-Utils.ps ps]]<br />
** Automatic skeletons in Template Haskell, by Kevin Hammond, Jost Berthold and Rita Loogen, June 2003. [[http://haskell.org/wikiupload/6/69/AutoSkelPPL03.pdf pdf]]<br />
** Optimising Embedded DSLs using Template Haskell, by Sean Seefried, Manuel Chakravarty, Gabriele Keller, March 2004. [[http://haskell.org/wikiupload/b/b5/Seefried04th-pan.pdf pdf]]<br />
** Typing Template Haskell: Soft Types, by Ian Lynagh, August 2004. [[http://haskell.org/wikiupload/7/72/Typing_Template_Haskell_Soft_Types.ps ps]]<br />
<br />
= Other useful resources =<br />
<br />
* [http://www.haskell.org/th/ The old Template Haskell web page]. Would someone feel like moving this material into the HaskellWiki?<br />
* Old and probably not too useful for most but maybe... http://www.cse.unsw.edu.au/~chak/haskell/ghc/comm/exts/th.html<br />
*[http://web.comlab.ox.ac.uk/oucl/work/ian.lynagh/Fraskell/ Fraskell documentation] & explanation of how Template Haskell is used to vastly speed it up.<br />
*[[Quasiquotation]]<br />
Feel free to update our Wikipedia entry<br />
http://en.wikipedia.org/wiki/Template_Haskell<br />
<br />
= Projects =<br />
<br />
What are you doing/planning to do/have done with Template Haskell?<br />
<br />
* The [http://www.ict.kth.se/org/ict/ecs/sam/projects/forsyde/www ForSyDe methodology] is currently implemented as a Haskell-based DSL which makes extensive use of Template Haskell.<br />
<br />
* I have written a primitive (untyped) binding to the Objective-C runtime system on Mac OS X. It needs just TH, no "stub files" are created, no seperate utilities are required. Initial snapshot is at http://www.kfunigraz.ac.at/imawww/thaller/wolfgang/HOC020103.tar.bz2 -- WolfgangThaller<br />
<br />
* I am writing Template Greencard - a reimplementation of GreenCard using TH. Many bits work out really nicely. A few bits didn't work so nicely - once I get some time to think, I'll try to persuade the TH folk to make some changes to fix some of these. -- AlastairReid<br />
<br />
* I'm writing Hacanon - a framework for automatic generation of C++ bindings. Read "automated Template Greencard for C++" (-: Darcs repo: http://www.ScannedInAvian.org/repos/hacanon - You'll need gccxml (http://www.gccxml.org/) to compile the exmples. - 27 Dec Lemmih.<br />
<br />
* Following other FFI tools developers, I see some future for Template HSFFIG, especially when it comes to autogenerate peek and poke methods for structures defined in C; may be useful for implementation of certain network protocols such as X11 where layout of messages is provided as C structure/union declaration. - 16 Dec 2005 DimitryGolubovsky<br />
<br />
* I am using Template Haskell as a mechanism to get parsed, typechecked code into an Ajax based Haskell Equational Reasoning tool [[Haskell Equational Reasoning Assistant]], as well as simplify the specification of equational relationships between pieces of code. There was a quicktime movie of the tool being used on http://www.gill-warbington.com/home/andy/share/hera1.html - AndyGill <br />
<br />
* I am working on functional metaprogramming techniques to enhance programming reliability and productivity, by reusing much of the existing compiler technology. Template Haskell is especially interesting for me because it permits to check size information of structures by the compiler, provided this information is available at compile time. This approach is especially appropriate for hardware designs, where the structures are fixed before the circuit starts operating. See our metaprogramming web page at http://www.infosun.fmi.uni-passau.de/cl/metaprog/ -- ChristophHerrmann(http://www.cs.st-and.ac.uk/~ch)<br />
<br />
* I am using Template Haskell to do type safe database access. I initially [http://www.nabble.com/Using-Template-Haskell-to-make-type-safe-database-access-td17027286.html proposed this on haskell-cafe]. I connect to the database at compile-time and let the database do SQL parsing and type inference. The result from parsing and type inference is used to build a type safe database query which can executed at run-time. [[MetaHDBC | You can find the project page here]] -- [mailto:mads_lindstroem@yahoo.dk Mads Lindstrøm]<br />
<br />
= Utilities =<br />
<br />
Helper functions, debugging functions, or more involved code e.g. a monadic fold algebra for TH.Syntax.<br />
<br />
* http://www.haskell.org/pipermail/template-haskell/2003-September/000176.html<br />
<br />
= Known Bugs =<br />
<br />
Take a look at the [http://hackage.haskell.org/trac/ghc/query?status=new&status=assigned&status=reopened&component=Template+Haskell&order=priority open bugs against Template Haskell] on the GHC bug tracker.<br />
<br />
= Wish list =<br />
<br />
Things that Ian Lynagh (Igloo) mentioned in his paper ''Template Haskell: A Report From The Field'' in May 2003 (available [http://www.haskell.org/th/papers.html here]), by section:<br />
<br />
* Section 2 (curses)<br />
** The ability to splice names (into "foreign import" declarations, in particular)<br />
** The ability to add things to the export list from a splice(?)<br />
** The ability to use things defined at the toplevel of a module from splices in that same module (would require multi-stage compilation, as opposed to the current approach of expanding splices during typechecking)<br />
<br />
* Section 3 (deriving instances of classes)<br />
** <strike>First-class reification</strike> (the <hask>reify</hask> function)<br />
** A way to discover whether a data constructor was defined infix or prefix (which is necessary to derive instances for <hask>Read</hask> and <hask>Show</hask> as outlined in [http://www.haskell.org/onlinereport/derived.html The Haskell 98 Report: Specification of Derived Instances]) (if there is a way, [http://www-users.cs.york.ac.uk/~ndm/derive/ Derive] seems ignorant of it)<br />
** Type/context splicing (in <hask>instance</hask> headers in particular)<br />
<br />
* Section 4 (printf)<br />
** He says something to the effect that a pattern-matching form of the quotation brackets would be cool if it was expressive enough to be useful, but that this would be hard. (Don't expect this anytime soon.)<br />
<br />
* Section 5 (fraskell)<br />
** Type information for quoted code (so that simplification can be done safely even with overloaded operations, like, oh, <hask>(+)</hask>)<br />
<br />
* Section 6 (pan)<br />
** Type info again, and strictnes info too (this one seems a bit pie-in-the-sky...)<br />
<br />
(Please leave the implemented ones here, but crossed off.)<br />
<br />
Any other features that may be nice, and TH projects you'd want to see.<br />
<br />
* A TH tutorial (mainly a distillation and update of ''Template Meta-programming in Haskell'' at this point)<br />
* <strike>Write Haddock documentation for the Template Haskell library (http://hackage.haskell.org/trac/ghc/ticket/1576).</strike><br />
* Make `reify` on a class return a list of the instances of that class (http://www.haskell.org/pipermail/template-haskell/2005-December/000503.html). (See also [http://hackage.haskell.org/trac/ghc/ticket/1577 GHC ticket #1577].)<br />
* A set of simple examples on this wiki page<br />
* A TH T-shirt with new logo to wear at conferences<br />
* (Long-term) Unify Language.Haskell.Syntax with Language.Haskell.TH.Syntax so there's just one way to do things (http://hackage.haskell.org/package/haskell-src-meta does a one-way translation, for haskell-src-exts)<br />
<br />
---------------<br />
<br />
= Tips and Tricks =<br />
<br />
== What to do when you can't splice that there ==<br />
<br />
When you try to splice something into the middle of a template and find that you just can't, instead of getting frustrated about it, why not use the template to see what it would look like in longhand? <br />
<br />
First, an excerpt from a module of my own. I, by the way, am SamB.<br />
<haskell><br />
{-# OPTIONS_GHC -fglasgow-exts -fth #-}<br />
<br />
module MMixMemory where<br />
<br />
import Data.Int<br />
import Data.Word<br />
<br />
class (Integral int, Integral word)<br />
=> SignConversion int word | int -> word, word -> int where<br />
<br />
toSigned :: word -> int<br />
toSigned = fromIntegral<br />
toUnsigned :: int -> word<br />
toUnsigned = fromIntegral<br />
<br />
</haskell><br />
<br />
Say I want to find out what I need to do to splice in the types for an instance declaration for the SignConversion class, so that I can declare instances for Int8 with Word8 through Int64 with Word64. So, I start up good-ol' GHCi and do the following:<br />
<br />
<haskell><br />
$ ghci -fth -fglasgow-exts<br />
Prelude> :l MMixMemory<br />
*MMixMemory> :m +Language.Haskell.TH.Syntax<br />
*MMixMemory Language.Haskell.TH.Syntax> runQ [d| instance SignConversion Int Word where |] >>= print<br />
[InstanceD [] (AppT (AppT (ConT MMixMemory.SignConversion) (ConT GHC.Base.Int)) (ConT GHC.Word.Word)) []]<br />
</haskell><br />
<br />
== What can <tt>reify</tt> see? ==<br />
<br />
When you use <tt>reify</tt> to give you information about a <tt>Name</tt>, GHC will tell you want it knows. But sometimes it doesn't know stuff. In particular<br />
<br />
* '''Imported things'''. When you reify an imported function, type constructor, class, etc, from (say) module M, GHC runs off to the interface file <tt>M.hi</tt> in which it deposited all the info it learned when compiling M. However, if you compiled M without optimisation (ie <tt>-O0</tt>, the default), and without <tt>-XTemplateHaskell</tt>, GHC tries to put as little info in the interface file as possible. (This is a possibly-misguided attempt to keep interface files small.) In particular, it may dump only the name and kind of a data type into <tt>M.hi</tt>, but not its constructors.<br />
: Under these circumstances you may reify a data type but get back no information about its data constructors or fields. Solution: compile M with <br />
:* <tt>-O</tt>, or<br />
:* <tt>-fno-omit-interface-pragmas</tt> (implied by -O), or<br />
:* <tt>-XTemplateHaskell</tt>.<br />
<br />
* '''Function definitions'''. The <tt>VarI</tt> constructor of the <tt>Info</tt> type advertises that you might get back the source code for a function definition. In fact, GHC currently (7.4) <em>always</em> returns <tt>Nothing</tt> in this field. It's a bit awkward and no one has really needed it.<br />
<br />
== Why does <tt>runQ</tt> crash if I try to reify something? ==<br />
<br />
This program will fail with an error message when you run it:<br />
<haskell><br />
main = do info <- runQ (reify (mkName "Bool")) -- more hygenic is: (reify ''Bool)<br />
putStrLn (pprint info)<br />
</haskell><br />
Reason: <tt>reify</tt> consults the type environment, and that is not available at run-time. The type of <tt>reify</tt> is <br />
<haskell><br />
reify :: Quasi m => Q a -> m a<br />
</haskell><br />
The IO monad is a poor-man's instance of <tt>Quasi</tt>; it can allocate unique names and gather error messages, but it can't do <tt>reify</tt>. This error should really be caught statically.<br />
<br />
Instead, you can run the splice directly (ex. in ghci -XTemplateHaskell), as the following shows:<br />
<br />
<haskell><br />
GHCi> let tup = $(tupE $ take 4 $ cycle [ [| "hi" |] , [| 5 |] ])<br />
GHCi> :type tup<br />
tup :: ([Char], Integer, [Char], Integer)<br />
<br />
GHCi> tup<br />
("hi",5,"hi",5)<br />
<br />
GHCi> $(stringE . show =<< reify ''Int)<br />
"TyConI (DataD [] GHC.Types.Int [] [NormalC GHC.Types.I# [(NotStrict,ConT GHC.Prim.Int#)]] [])"<br />
</haskell><br />
<br />
Here's an [http://www.haskell.org/pipermail/glasgow-haskell-users/2006-August/010844.html email thread with more details].<br />
<br />
-----------------<br />
<br />
= Examples =<br />
== Tuples ==<br />
=== Select from a tuple ===<br />
<br />
An example to select an element from a tuple of arbitrary size. Taken from [http://www.haskell.org/th/papers/meta-haskell.ps this paper].<br />
<br />
Use like so:<br />
<br />
> $(sel 2 3) ('a','b','c')<br />
'b'<br />
> $(sel 3 4) ('a','b','c','d')<br />
'c'<br />
<br />
<br />
<haskell><br />
sel :: Int -> Int -> ExpQ<br />
sel i n = [| \x -> $(caseE [| x |] [alt]) |]<br />
where alt :: MatchQ<br />
alt = match pat (normalB rhs) []<br />
<br />
pat :: Pat<br />
pat = tupP (map varP as)<br />
<br />
rhs :: ExpQ<br />
rhs = varE(as !! (i -1)) -- !! is 0 based<br />
<br />
as :: [String]<br />
as = ["a" ++ show i | i <- [1..n] ]<br />
</haskell><br />
<br />
Alternately:<br />
<br />
<haskell><br />
sel' i n = lamE [pat] rhs<br />
where pat = tupP (map varP as)<br />
rhs = varE (as !! (i - 1))<br />
as = [ "a" ++ show j | j <- [1..n] ]<br />
</haskell><br />
<br />
=== Apply a function to the n'th element ===<br />
<br />
<haskell><br />
tmap i n = do<br />
f <- newName "f"<br />
as <- replicateM n (newName "a")<br />
lamE [varP f, tupP (map varP as)] $<br />
tupE [ if i == i'<br />
then [| $(varE f) $a |]<br />
else a<br />
| (a,i') <- map varE as `zip` [1..] ]<br />
</haskell><br />
<br />
Then tmap can be called as:<br />
<br />
> $(tmap 3 4) (+ 1) (1,2,3,4)<br />
(1,2,4,4)<br />
<br />
=== Convert the first n elements of a list to a tuple ===<br />
<br />
This example creates a tuple by extracting elemnts from a list. Taken from<br />
[http://www.xoltar.org/2003/aug/13/templateHaskellTupleSample.html www.xoltar.org]<br />
<br />
Use like so:<br />
<br />
> $(tuple 3) [1,2,3,4,5]<br />
(1,2,3)<br />
> $(tuple 2) [1,2]<br />
(1,2)<br />
<br />
<haskell><br />
tuple :: Int -> ExpQ<br />
tuple n = [|\list -> $(tupE (exprs [|list|])) |]<br />
where<br />
exprs list = [infixE (Just (list))<br />
(varE "!!")<br />
(Just (litE $ integerL (toInteger num)))<br />
| num <- [0..(n - 1)]]<br />
</haskell><br />
<br />
An alternative that has more informative errors (a failing pattern match failures give an exact location):<br />
<br />
<haskell><br />
tuple :: Int -> ExpQ<br />
tuple n = do<br />
ns <- replicateM n (newName "x")<br />
lamE [foldr (\x y -> conP '(:) [varP x,y]) wildP ns] (tupE $ map varE ns)<br />
</haskell><br />
<br />
=== Un-nest tuples ===<br />
Convert nested tuples like (a,(b,(c,()))) into (a,b,c) given the length to generate.<br />
<br />
<haskell><br />
unNest n = do<br />
vs <- replicateM n (newName "x")<br />
lamE [foldr (\a b -> tupP [varP a , b])<br />
(conP '() [])<br />
vs]<br />
(tupE (map varE vs))<br />
</haskell><br />
<br />
<br />
<br />
== [[Template Haskell/Marshall Data|Marshall a datatype to and from Dynamic]] ==<br />
This approach is an example of using template haskell to delay typechecking<br />
to be able to abstract out the repeated calls to fromDynamic:<br />
<br />
<haskell><br />
data T = T Int String Double<br />
<br />
toT :: [Dynamic] -> Maybe T<br />
toT [a,b,c] = do<br />
a' <- fromDynamic a<br />
b' <- fromDynamic b<br />
c' <- fromDynamic c<br />
return (T a' b' c')<br />
toT _ = Nothing<br />
</haskell><br />
<br />
== Printf ==<br />
Build it using a command similar to:<br />
<br />
ghc --make Main.hs -o main<br />
<br />
Main.hs:<br />
<br />
<haskell><br />
{-# LANGUAGE TemplateHaskell #-}<br />
<br />
-- Import our template "printf"<br />
import PrintF (printf)<br />
<br />
-- The splice operator $ takes the Haskell source code<br />
-- generated at compile time by "printf" and splices it into<br />
-- the argument of "putStrLn".<br />
main = do<br />
putStrLn $ $(printf "Hello %s %%x%% %d %%x%%") "World" 12<br />
</haskell><br />
<br />
PrintF.hs:<br />
<br />
<haskell><br />
{-# LANGUAGE TemplateHaskell #-}<br />
module PrintF where<br />
<br />
-- NB: printf needs to be in a separate module to the one where<br />
-- you intend to use it.<br />
<br />
-- Import some Template Haskell syntax<br />
import Language.Haskell.TH<br />
<br />
-- Possible string tokens: %d %s and literal strings<br />
data Format = D | S | L String<br />
deriving Show<br />
<br />
-- a poor man's tokenizer<br />
tokenize :: String -> [Format]<br />
tokenize [] = []<br />
tokenize ('%':c:rest) | c == 'd' = D : tokenize rest<br />
| c == 's' = S : tokenize rest<br />
tokenize (s:str) = L (s:p) : tokenize rest -- so we don't get stuck on weird '%'<br />
where (p,rest) = span (/= '%') str<br />
<br />
-- generate argument list for the function<br />
args :: [Format] -> [PatQ]<br />
args fmt = concatMap (\(f,n) -> case f of<br />
L _ -> []<br />
_ -> [varP n]) $ zip fmt names<br />
where names = [ mkName $ 'x' : show i | i <- [0..] ]<br />
<br />
-- generate body of the function<br />
body :: [Format] -> ExpQ<br />
body fmt = foldr (\ e e' -> infixApp e [| (++) |] e') (last exps) (init exps)<br />
where exps = [ case f of<br />
L s -> stringE s<br />
D -> appE [| show |] (varE n)<br />
S -> varE n<br />
| (f,n) <- zip fmt names ]<br />
names = [ mkName $ 'x' : show i | i <- [0..] ]<br />
<br />
-- glue the argument list and body together into a lambda<br />
-- this is what gets spliced into the haskell code at the call<br />
-- site of "printf"<br />
printf :: String -> Q Exp<br />
printf format = lamE (args fmt) (body fmt)<br />
where fmt = tokenize format<br />
</haskell><br />
<br />
== Handling Options with Templates ==<br />
A common idiom for treating a set of options, e.g. from GetOpt, is to define a datatype with all the flags and using a list over this datatype:<br />
<br />
<haskell><br />
data Options = B1 | B2 | V Integer<br />
<br />
options = [B1, V 3]<br />
</haskell><br />
<br />
While it's simple testing if a Boolean flag is set (simply use "elem"), it's harder to check if an option with an argument is set. It's even more tedious writing helper-functions to obtain the value from such an option since you have to explicitely "un-V" each. Here, Template Haskell can be (ab)used to reduce this a bit. The following example provides the module "OptionsTH" which can be reused regardless of the constructors in "Options". Let's start with showing how we'd like to be able to program. Notice that the resulting lists need some more treatment e.g. through "foldl".<br />
<br />
Options.hs:<br />
<br />
<haskell><br />
module Main where<br />
<br />
import OptionsTH<br />
import Language.Haskell.TH.Syntax<br />
<br />
data Options = B1 | B2 | V Int | S String deriving (Eq, Read, Show)<br />
<br />
options = [B1, V 3]<br />
<br />
main = do<br />
print foo -- test if B1 set: [True,False]<br />
print bar -- test if V present, w/o value: [False,True]<br />
print baz -- get value of V if available: [Nothing,Just 3]<br />
<br />
foo :: [Bool]<br />
-- Query constructor B1 which takes no arguments<br />
foo = map $(getopt (THNoArg (mkArg "B1" 0))) options<br />
<br />
bar :: [Bool]<br />
-- V is a unary constructor. Let mkArg generate the required<br />
-- wildcard-pattern "V _".<br />
bar = map $(getopt (THNoArg (mkArg "V" 1))) options<br />
<br />
-- Can't use a wildcard here!<br />
baz :: [(Maybe Int)]<br />
baz = map $(getopt (THArg (conP "V" [varP "x"]))) options<br />
</haskell><br />
<br />
OptionsTH.hs<br />
<br />
<haskell><br />
module OptionsTH where<br />
<br />
import Language.Haskell.TH.Syntax<br />
<br />
-- datatype for querying options:<br />
-- NoArg: Not interested in value (also applies to Boolean flags)<br />
-- Arg: Grep value of unary(!) constructor<br />
data Args = THNoArg Pat | THArg Pat<br />
<br />
getopt :: Args -> ExpQ<br />
getopt (THNoArg pat) = lamE [varP "y"] (caseE (varE "y") [cons0, cons1])<br />
where<br />
cons0 = match pat (normalB [| True |]) []<br />
cons1 = match wildP (normalB [| False |]) []<br />
<br />
-- bind "var" for later use!<br />
getopt (THArg pat@(ConP _ [VarP var])) = lamE [varP "y"] (caseE (varE "y") [cons0, cons1])<br />
where<br />
cons0 = match pat (normalB (appE [|Just|] (varE var))) []<br />
cons1 = match wildP (normalB [|Nothing|]) []<br />
<br />
mkArg :: String -> Int -> Pat<br />
mkArg k c = conP k (replicate c wildP)<br />
</haskell><br />
<br />
While the example might look contrived for the Boolean options which could have been tested much easier, it shows how both types of arguments can be treated in a similar way.<br />
<br />
=== Limitations ===<br />
<tt>getopt (THArg pat)</tt> is only able to treat unary constructors. See the pattern-binding: It matches exactly a single VarP.<br />
<br />
=== Improvements ===<br />
The following reduces things even a bit more, though I still don't know if I like it. It only works since <tt>c</tt> is either 0 or 1.<br />
<br />
<haskell><br />
mkArg k c = conP k (replicate c (varP "x"))<br />
<br />
baz = map $(getopt (THArg (mkArg "V" 1)))<br />
</haskell><br />
-- VolkerStolz<br />
<br />
== Generic constructor for records ==<br />
<br />
I have a large number of record types like this, of different length:<br />
<br />
<haskell><br />
data PGD = PGD {<br />
pgdXUnitBase :: !Word8,<br />
pgdYUnitBase :: !Word8,<br />
pgdXLUnitsperUnitBase :: !Word16<br />
}<br />
</haskell><br />
<br />
Currently I use GHC's Binary module to read them from files; it can handle<br />
types like <tt>(Word8, (Word8, Word16))</tt>, but there was no easy way to generate<br />
the correct amount of "uncurry" calls for automatically grabbing each element.<br />
<br />
With Template Haskell, the instance declarations are now written as such:<br />
<br />
<haskell><br />
instance Binary PGD where<br />
get bh = do a <- get bh ; return $ $(constrRecord PGD) a<br />
</haskell><br />
<br />
Here the trick lies in constrRecord, which is defined as:<br />
<br />
<haskell><br />
constrRecord x = reify exp where<br />
reify = \(Just r) -> appE r $ conE $ last args<br />
exp = foldl (dot) uncur $ replicate terms uncur<br />
terms = ((length args) `div` 2) - 2<br />
dot x y = (Just $ infixE x (varE ".") y)<br />
uncur = (Just [|uncurry|])<br />
args = words . show $ typeOf x<br />
</haskell><br />
<br />
-- AutrijusTang<br />
<br />
== zipWithN ==<br />
<br />
Here $(zipn 3) = zipWith3 etc.<br />
<br />
<haskell><br />
import Language.Haskell.TH; import Control.Applicative; import Control.Monad<br />
<br />
zipn n = do<br />
vs <- replicateM n (newName "vs")<br />
[| \f -><br />
$(lamE (map varP vs)<br />
[| getZipList $<br />
$(foldl<br />
(\a b -> [| $a <*> $b |])<br />
[| pure f |]<br />
(map (\v -> [| ZipList $(varE v) |]) vs))<br />
|])<br />
|]<br />
</haskell><br />
<br />
== 'generic' zipWith ==<br />
A generalization of zipWith to almost any data. Demonstrates the ability to do dynamic binding with TH splices (note 'dyn').<br />
<br />
<haskell><br />
zipCons :: Name -> Int -> [String] -> ExpQ<br />
zipCons tyName ways functions = do<br />
let countFields :: Con -> (Name,Int)<br />
countFields x = case x of<br />
NormalC n (length -> fields) -> (n, fields)<br />
RecC n (length -> fields) -> (n,fields)<br />
InfixC _ n _ -> (n,2)<br />
ForallC _ _ ct -> countFields ct<br />
<br />
TyConI (DataD _ _ _ [countFields -> (c,n)] _) <- reify tyName<br />
when (n /= length functions) $ fail "wrong number of functions named"<br />
vs <- replicateM ways $ replicateM n $ newName "x"<br />
lamE (map (conP c . map varP) vs) $<br />
foldl (\con (vs,f) -><br />
con `appE`<br />
foldl appE<br />
(dyn f)<br />
(map varE vs))<br />
(conE c)<br />
(transpose vs `zip` functions)<br />
</haskell><br />
<br />
This example uses whichever '+' is in scope when the expression is spliced:<br />
<br />
<haskell><br />
:type $(zipCons ''(,,,) 2 (replicate 4 "+"))<br />
<br />
$(zipCons ''(,,,) 2 (replicate 4 "+"))<br />
:: (Num t, Num t1, Num t2, Num t3) =><br />
(t, t1, t2, t3) -> (t, t1, t2, t3) -> (t, t1, t2, t3)<br />
</haskell><br />
<br />
==[[Template haskell/Instance deriving example|Instance deriving example]]==<br />
An example using a 'deriving function' to generate a method instance <br />
per constructor of a type. The deriving function provides the body of the<br />
method.<br />
<br />
Note that this example assumes that the functions of the class take a parameter that is the same type as instance is parameterized with. <br />
<br />
The message [http://www.haskell.org/pipermail/template-haskell/2006-August/000581.html email message] contains the full source ([http://www.iist.unu.edu/~vs/haskell/TH_render.hs extracted file]).<br />
<br />
== [[Quasiquotation|QuasiQuoters]] ==<br />
New in ghc-6.10 is -XQuasiQuotes, which allows one to extend ghc's syntax from library code. Quite a few examples are given in [http://hackage.haskell.org/package/haskell-src-meta haskell-src-meta].<br />
<br />
=== Similarity with splices ===<br />
<br />
Quasiquoters used in expression contexts (those using the ''quoteExp'') behave to a first approximation like regular TH splices:<br />
<br />
<haskell><br />
simpleQQ = QuasiQuoter { quoteExp = stringE } -- in another module<br />
<br />
[$simpleQQ| a b c d |] == $(quoteExp simpleQQ " a b c d ")<br />
</haskell><br />
<br />
[[Category:Language extensions]]</div>Simonpjhttps://wiki.haskell.org/index.php?title=Template_Haskell&diff=41983Template Haskell2011-09-09T11:37:39Z<p>Simonpj: /* What can reify see? */</p>
<hr />
<div>'''[http://hackage.haskell.org/package/template-haskell Template Haskell]''' is a [[GHC]] extension to Haskell that adds compile-time metaprogramming facilities. The original design can be found here: http://research.microsoft.com/~simonpj/papers/meta-haskell/ . It is [http://haskell.cs.yale.edu/ghc/docs/6.2/html/users_guide/template-haskell.html included] in GHC version 6. <br />
<br />
This page hopes to be a more central and organized repository of TH related things.<br />
<br />
=What is Template Haskell?=<br />
Template Haskell is an extension to Haskell 98 that allows you to do type-safe compile-time meta-programming, with Haskell both as the manipulating language and the language being manipulated. <br />
<br />
Intuitively Template Haskell provides new language features that allow us to convert back and forth between concrete syntax, i.e. what you would type when you write normal Haskell code, and abstract syntax trees. These abstract syntax trees are represented using Haskell datatypes and, at compile time, they can be manipulated by Haskell code. This allows you to reify (convert from concrete syntax to an abstract syntax tree) some code, transform it and splice it back in (convert back again), or even to produce completely new code and splice that in, while the compiler is compiling your module. <br />
<br />
For email about Template Haskell, use the [http://haskell.org/mailman/listinfo/glasgow-haskell-users GHC users mailing list]. It's worth joining if you start to use TH.<br />
<br />
= Template Haskell specification =<br />
<br />
Template Haskell is only documented rather informally at the moment. Here are the main resources:<br />
<br />
* [http://www.haskell.org/ghc/docs/latest/html/users_guide/template-haskell.html The user manual section on Template Haskell]<br />
* [http://www.haskell.org/ghc/docs/latest/html/users_guide/template-haskell.html#th-quasiquotation The user manual section on quasi-quotation], which is closely related to Template Haskell.<br />
* [http://research.microsoft.com/~simonpj/papers/meta-haskell/ The original Template Haskell paper]<br />
* [http://research.microsoft.com/~simonpj/tmp/notes2.ps Notes on Template Haskell version 2], which describes changes since the original paper. Section 8 describes the difficulty with pattern splices, which are therefore not implemented.<br />
* [http://haskell.org/ghc/docs/7.0-latest/html/libraries/template-haskell-2.5.0.0/Language-Haskell-TH.html The Template Haskell API]<br />
<br />
= Template Haskell tutorials and papers =<br />
<br />
* Bulat's tutorials:<br />
** [http://docs.google.com/uc?id=0B4BgTwf_ng_TM2MxZjJjZjctMTQ0OS00YzcwLWE5N2QtMDI0YzE4NGUwZDM3 [formerly /bz/thdoc.htm]]<br />
** [http://docs.google.com/uc?id=0B4BgTwf_ng_TOGJkZjM4ZTUtNGY5My00ZThhLTllNDQtYzJjMWJiMzJhZjNj [formerly /bz/th3.htm]]<br />
<br />
: One reader said "These docs are *brilliant* ! Exactly what I need to get an understanding of TH."<br />
<br />
<small>(Note: These documents are from [http://www.archive.org the Wayback machine] because the originals disappeared. They're public documents on Google docs, which shouldn't require logging in. However, if you're asked to sign in to view them, you're running into a known Google bug. You can fix it by browsing to [http://www.google.com Google], presumably gaining a cookie in the process.)</small><br />
<br />
* Mark Snyder's Template Haskell chapter on the Software Generation and Configuration Report<br />
** http://nix.cs.uu.nl/dist/courses/sgc-report-unstable-latest/manual/chunk-chapter/templatehaskell.html<br />
<br />
* A very short tutorial to understand the basics in 10 Minutes.<br />
** http://www.hyperedsoftware.com/blog/entries/first-stab-th.html<br />
<br />
* GHC Template Haskell documentation<br />
** http://www.haskell.org/ghc/docs/7.0.2/html/users_guide/template-haskell.html<br />
<br />
* Papers about Template Haskell<br />
<br />
** Template metaprogramming for Haskell, by Tim Sheard and Simon Peyton Jones, Oct 2002. [[http://haskell.org/wikiupload/c/ca/Meta-haskell.ps ps]]<br />
** Template Haskell: A Report From The Field, by Ian Lynagh, May 2003. [[http://haskell.org/wikiupload/2/24/Template_Haskell-A_Report_From_The_Field.ps ps]]<br />
** Unrolling and Simplifying Expressions with Template Haskell, by Ian Lynagh, December 2002. [[http://haskell.org/wikiupload/e/ed/Template-Haskell-Utils.ps ps]]<br />
** Automatic skeletons in Template Haskell, by Kevin Hammond, Jost Berthold and Rita Loogen, June 2003. [[http://haskell.org/wikiupload/6/69/AutoSkelPPL03.pdf pdf]]<br />
** Optimising Embedded DSLs using Template Haskell, by Sean Seefried, Manuel Chakravarty, Gabriele Keller, March 2004. [[http://haskell.org/wikiupload/b/b5/Seefried04th-pan.pdf pdf]]<br />
** Typing Template Haskell: Soft Types, by Ian Lynagh, August 2004. [[http://haskell.org/wikiupload/7/72/Typing_Template_Haskell_Soft_Types.ps ps]]<br />
<br />
= Other useful resources =<br />
<br />
* [http://www.haskell.org/th/ The old Template Haskell web page]. Would someone feel like moving this material into the HaskellWiki?<br />
* Old and probably not too useful for most but maybe... http://www.cse.unsw.edu.au/~chak/haskell/ghc/comm/exts/th.html<br />
*[http://web.comlab.ox.ac.uk/oucl/work/ian.lynagh/Fraskell/ Fraskell documentation] & explanation of how Template Haskell is used to vastly speed it up.<br />
*[[Quasiquotation]]<br />
Feel free to update our Wikipedia entry<br />
http://en.wikipedia.org/wiki/Template_Haskell<br />
<br />
= Projects =<br />
<br />
What are you doing/planning to do/have done with Template Haskell?<br />
<br />
* The [http://www.ict.kth.se/org/ict/ecs/sam/projects/forsyde/www ForSyDe methodology] is currently implemented as a Haskell-based DSL which makes extensive use of Template Haskell.<br />
<br />
* I have written a primitive (untyped) binding to the Objective-C runtime system on Mac OS X. It needs just TH, no "stub files" are created, no seperate utilities are required. Initial snapshot is at http://www.kfunigraz.ac.at/imawww/thaller/wolfgang/HOC020103.tar.bz2 -- WolfgangThaller<br />
<br />
* I am writing Template Greencard - a reimplementation of GreenCard using TH. Many bits work out really nicely. A few bits didn't work so nicely - once I get some time to think, I'll try to persuade the TH folk to make some changes to fix some of these. -- AlastairReid<br />
<br />
* I'm writing Hacanon - a framework for automatic generation of C++ bindings. Read "automated Template Greencard for C++" (-: Darcs repo: http://www.ScannedInAvian.org/repos/hacanon - You'll need gccxml (http://www.gccxml.org/) to compile the exmples. - 27 Dec Lemmih.<br />
<br />
* Following other FFI tools developers, I see some future for Template HSFFIG, especially when it comes to autogenerate peek and poke methods for structures defined in C; may be useful for implementation of certain network protocols such as X11 where layout of messages is provided as C structure/union declaration. - 16 Dec 2005 DimitryGolubovsky<br />
<br />
* I am using Template Haskell as a mechanism to get parsed, typechecked code into an Ajax based Haskell Equational Reasoning tool [[Haskell Equational Reasoning Assistant]], as well as simplify the specification of equational relationships between pieces of code. There was a quicktime movie of the tool being used on http://www.gill-warbington.com/home/andy/share/hera1.html - AndyGill <br />
<br />
* I am working on functional metaprogramming techniques to enhance programming reliability and productivity, by reusing much of the existing compiler technology. Template Haskell is especially interesting for me because it permits to check size information of structures by the compiler, provided this information is available at compile time. This approach is especially appropriate for hardware designs, where the structures are fixed before the circuit starts operating. See our metaprogramming web page at http://www.infosun.fmi.uni-passau.de/cl/metaprog/ -- ChristophHerrmann(http://www.cs.st-and.ac.uk/~ch)<br />
<br />
* I am using Template Haskell to do type safe database access. I initially [http://www.nabble.com/Using-Template-Haskell-to-make-type-safe-database-access-td17027286.html proposed this on haskell-cafe]. I connect to the database at compile-time and let the database do SQL parsing and type inference. The result from parsing and type inference is used to build a type safe database query which can executed at run-time. [[MetaHDBC | You can find the project page here]] -- [mailto:mads_lindstroem@yahoo.dk Mads Lindstrøm]<br />
<br />
= Utilities =<br />
<br />
Helper functions, debugging functions, or more involved code e.g. a monadic fold algebra for TH.Syntax.<br />
<br />
* http://www.haskell.org/pipermail/template-haskell/2003-September/000176.html<br />
<br />
= Known Bugs =<br />
<br />
Take a look at the [http://hackage.haskell.org/trac/ghc/query?status=new&status=assigned&status=reopened&component=Template+Haskell&order=priority open bugs against Template Haskell] on the GHC bug tracker.<br />
<br />
= Wish list =<br />
<br />
Things that Ian Lynagh (Igloo) mentioned in his paper ''Template Haskell: A Report From The Field'' in May 2003 (available [http://www.haskell.org/th/papers.html here]), by section:<br />
<br />
* Section 2 (curses)<br />
** The ability to splice names (into "foreign import" declarations, in particular)<br />
** The ability to add things to the export list from a splice(?)<br />
** The ability to use things defined at the toplevel of a module from splices in that same module (would require multi-stage compilation, as opposed to the current approach of expanding splices during typechecking)<br />
<br />
* Section 3 (deriving instances of classes)<br />
** <strike>First-class reification</strike> (the <hask>reify</hask> function)<br />
** A way to discover whether a data constructor was defined infix or prefix (which is necessary to derive instances for <hask>Read</hask> and <hask>Show</hask> as outlined in [http://www.haskell.org/onlinereport/derived.html The Haskell 98 Report: Specification of Derived Instances]) (if there is a way, [http://www-users.cs.york.ac.uk/~ndm/derive/ Derive] seems ignorant of it)<br />
** Type/context splicing (in <hask>instance</hask> headers in particular)<br />
<br />
* Section 4 (printf)<br />
** He says something to the effect that a pattern-matching form of the quotation brackets would be cool if it was expressive enough to be useful, but that this would be hard. (Don't expect this anytime soon.)<br />
<br />
* Section 5 (fraskell)<br />
** Type information for quoted code (so that simplification can be done safely even with overloaded operations, like, oh, <hask>(+)</hask>)<br />
<br />
* Section 6 (pan)<br />
** Type info again, and strictnes info too (this one seems a bit pie-in-the-sky...)<br />
<br />
(Please leave the implemented ones here, but crossed off.)<br />
<br />
Any other features that may be nice, and TH projects you'd want to see.<br />
<br />
* A TH tutorial (mainly a distillation and update of ''Template Meta-programming in Haskell'' at this point)<br />
* <strike>Write Haddock documentation for the Template Haskell library (http://hackage.haskell.org/trac/ghc/ticket/1576).</strike><br />
* Make `reify` on a class return a list of the instances of that class (http://www.haskell.org/pipermail/template-haskell/2005-December/000503.html). (See also [http://hackage.haskell.org/trac/ghc/ticket/1577 GHC ticket #1577].)<br />
* A set of simple examples on this wiki page<br />
* A TH T-shirt with new logo to wear at conferences<br />
* (Long-term) Unify Language.Haskell.Syntax with Language.Haskell.TH.Syntax so there's just one way to do things (http://hackage.haskell.org/package/haskell-src-meta does a one-way translation, for haskell-src-exts)<br />
<br />
---------------<br />
<br />
= Tips and Tricks =<br />
<br />
== What to do when you can't splice that there ==<br />
<br />
When you try to splice something into the middle of a template and find that you just can't, instead of getting frustrated about it, why not use the template to see what it would look like in longhand? <br />
<br />
First, an excerpt from a module of my own. I, by the way, am SamB.<br />
<haskell><br />
{-# OPTIONS_GHC -fglasgow-exts -fth #-}<br />
<br />
module MMixMemory where<br />
<br />
import Data.Int<br />
import Data.Word<br />
<br />
class (Integral int, Integral word)<br />
=> SignConversion int word | int -> word, word -> int where<br />
<br />
toSigned :: word -> int<br />
toSigned = fromIntegral<br />
toUnsigned :: int -> word<br />
toUnsigned = fromIntegral<br />
<br />
</haskell><br />
<br />
Say I want to find out what I need to do to splice in the types for an instance declaration for the SignConversion class, so that I can declare instances for Int8 with Word8 through Int64 with Word64. So, I start up good-ol' GHCi and do the following:<br />
<br />
<haskell><br />
$ ghci -fth -fglasgow-exts<br />
Prelude> :l MMixMemory<br />
*MMixMemory> :m +Language.Haskell.TH.Syntax<br />
*MMixMemory Language.Haskell.TH.Syntax> runQ [d| instance SignConversion Int Word where |] >>= print<br />
[InstanceD [] (AppT (AppT (ConT MMixMemory.SignConversion) (ConT GHC.Base.Int)) (ConT GHC.Word.Word)) []]<br />
</haskell><br />
<br />
== What can <tt>reify</tt> see? ==<br />
<br />
When you use <tt>reify</tt> to give you information about a <tt>Name</tt>, GHC will tell you want it knows. But sometimes it doesn't know stuff. In particular<br />
<br />
* '''Imported things'''. When you reify an imported function, type constructor, class, etc, from (say) module M, GHC runs off to the interface file <tt>M.hi</tt> in which it deposited all the info it learned when compiling M. However, if you compiled M without optimisation (ie <tt>-O0</tt>, the default), and without <tt>-XTemplateHaskell</tt>, GHC tries to put as little info in the interface file as possible. (This is a possibly-misguided attempt to keep interface files small.) In particular, it may dump only the name and kind of a data type into <tt>M.hi</tt>, but not its constructors.<br />
: Under these circumstances you may reify a data type but get back no information about its data constructors or fields. Solution: compile M with <tt>-O</tt> or <tt>-XTemplateHaskell</tt>.<br />
<br />
* '''Function definitions'''. The <tt>VarI</tt> constructor of the <tt>Info</tt> type advertises that you might get back the source code for a function definition. In fact, GHC currently (7.4) <em>always</em> returns <tt>Nothing</tt> in this field. (It's a bit awkward and no one has really needed it.)<br />
<br />
== Why does <tt>runQ</tt> crash if I try to reify something? ==<br />
<br />
This program will fail with an error message when you run it:<br />
<haskell><br />
main = do info <- runQ (reify (mkName "Bool")) -- more hygenic is: (reify ''Bool)<br />
putStrLn (pprint info)<br />
</haskell><br />
Reason: <tt>reify</tt> consults the type environment, and that is not available at run-time. The type of <tt>reify</tt> is <br />
<haskell><br />
reify :: Quasi m => Q a -> m a<br />
</haskell><br />
The IO monad is a poor-man's instance of <tt>Quasi</tt>; it can allocate unique names and gather error messages, but it can't do <tt>reify</tt>. This error should really be caught statically.<br />
<br />
Instead, you can run the splice directly (ex. in ghci -XTemplateHaskell), as the following shows:<br />
<br />
<haskell><br />
GHCi> let tup = $(tupE $ take 4 $ cycle [ [| "hi" |] , [| 5 |] ])<br />
GHCi> :type tup<br />
tup :: ([Char], Integer, [Char], Integer)<br />
<br />
GHCi> tup<br />
("hi",5,"hi",5)<br />
<br />
GHCi> $(stringE . show =<< reify ''Int)<br />
"TyConI (DataD [] GHC.Types.Int [] [NormalC GHC.Types.I# [(NotStrict,ConT GHC.Prim.Int#)]] [])"<br />
</haskell><br />
<br />
Here's an [http://www.haskell.org/pipermail/glasgow-haskell-users/2006-August/010844.html email thread with more details].<br />
<br />
-----------------<br />
<br />
= Examples =<br />
== Tuples ==<br />
=== Select from a tuple ===<br />
<br />
An example to select an element from a tuple of arbitrary size. Taken from [http://www.haskell.org/th/papers/meta-haskell.ps this paper].<br />
<br />
Use like so:<br />
<br />
> $(sel 2 3) ('a','b','c')<br />
'b'<br />
> $(sel 3 4) ('a','b','c','d')<br />
'c'<br />
<br />
<br />
<haskell><br />
sel :: Int -> Int -> ExpQ<br />
sel i n = [| \x -> $(caseE [| x |] [alt]) |]<br />
where alt :: MatchQ<br />
alt = match pat (normalB rhs) []<br />
<br />
pat :: Pat<br />
pat = tupP (map varP as)<br />
<br />
rhs :: ExpQ<br />
rhs = varE(as !! (i -1)) -- !! is 0 based<br />
<br />
as :: [String]<br />
as = ["a" ++ show i | i <- [1..n] ]<br />
</haskell><br />
<br />
Alternately:<br />
<br />
<haskell><br />
sel' i n = lamE [pat] rhs<br />
where pat = tupP (map varP as)<br />
rhs = varE (as !! (i - 1))<br />
as = [ "a" ++ show j | j <- [1..n] ]<br />
</haskell><br />
<br />
=== Apply a function to the n'th element ===<br />
<br />
<haskell><br />
tmap i n = do<br />
f <- newName "f"<br />
as <- replicateM n (newName "a")<br />
lamE [varP f, tupP (map varP as)] $<br />
tupE [ if i == i'<br />
then [| $(varE f) $a |]<br />
else a<br />
| (a,i') <- map varE as `zip` [1..] ]<br />
</haskell><br />
<br />
Then tmap can be called as:<br />
<br />
> $(tmap 3 4) (+ 1) (1,2,3,4)<br />
(1,2,4,4)<br />
<br />
=== Convert the first n elements of a list to a tuple ===<br />
<br />
This example creates a tuple by extracting elemnts from a list. Taken from<br />
[http://www.xoltar.org/2003/aug/13/templateHaskellTupleSample.html www.xoltar.org]<br />
<br />
Use like so:<br />
<br />
> $(tuple 3) [1,2,3,4,5]<br />
(1,2,3)<br />
> $(tuple 2) [1,2]<br />
(1,2)<br />
<br />
<haskell><br />
tuple :: Int -> ExpQ<br />
tuple n = [|\list -> $(tupE (exprs [|list|])) |]<br />
where<br />
exprs list = [infixE (Just (list))<br />
(varE "!!")<br />
(Just (litE $ integerL (toInteger num)))<br />
| num <- [0..(n - 1)]]<br />
</haskell><br />
<br />
An alternative that has more informative errors (a failing pattern match failures give an exact location):<br />
<br />
<haskell><br />
tuple :: Int -> ExpQ<br />
tuple n = do<br />
ns <- replicateM n (newName "x")<br />
lamE [foldr (\x y -> conP '(:) [varP x,y]) wildP ns] (tupE $ map varE ns)<br />
</haskell><br />
<br />
=== Un-nest tuples ===<br />
Convert nested tuples like (a,(b,(c,()))) into (a,b,c) given the length to generate.<br />
<br />
<haskell><br />
unNest n = do<br />
vs <- replicateM n (newName "x")<br />
lamE [foldr (\a b -> tupP [varP a , b])<br />
(conP '() [])<br />
vs]<br />
(tupE (map varE vs))<br />
</haskell><br />
<br />
<br />
<br />
== [[Template Haskell/Marshall Data|Marshall a datatype to and from Dynamic]] ==<br />
This approach is an example of using template haskell to delay typechecking<br />
to be able to abstract out the repeated calls to fromDynamic:<br />
<br />
<haskell><br />
data T = T Int String Double<br />
<br />
toT :: [Dynamic] -> Maybe T<br />
toT [a,b,c] = do<br />
a' <- fromDynamic a<br />
b' <- fromDynamic b<br />
c' <- fromDynamic c<br />
return (T a' b' c')<br />
toT _ = Nothing<br />
</haskell><br />
<br />
== Printf ==<br />
Build it using a command similar to:<br />
<br />
ghc --make Main.hs -o main<br />
<br />
Main.hs:<br />
<br />
<haskell><br />
{-# LANGUAGE TemplateHaskell #-}<br />
<br />
-- Import our template "printf"<br />
import PrintF (printf)<br />
<br />
-- The splice operator $ takes the Haskell source code<br />
-- generated at compile time by "printf" and splices it into<br />
-- the argument of "putStrLn".<br />
main = do<br />
putStrLn $ $(printf "Hello %s %%x%% %d %%x%%") "World" 12<br />
</haskell><br />
<br />
PrintF.hs:<br />
<br />
<haskell><br />
{-# LANGUAGE TemplateHaskell #-}<br />
module PrintF where<br />
<br />
-- NB: printf needs to be in a separate module to the one where<br />
-- you intend to use it.<br />
<br />
-- Import some Template Haskell syntax<br />
import Language.Haskell.TH<br />
<br />
-- Possible string tokens: %d %s and literal strings<br />
data Format = D | S | L String<br />
deriving Show<br />
<br />
-- a poor man's tokenizer<br />
tokenize :: String -> [Format]<br />
tokenize [] = []<br />
tokenize ('%':c:rest) | c == 'd' = D : tokenize rest<br />
| c == 's' = S : tokenize rest<br />
tokenize (s:str) = L (s:p) : tokenize rest -- so we don't get stuck on weird '%'<br />
where (p,rest) = span (/= '%') str<br />
<br />
-- generate argument list for the function<br />
args :: [Format] -> [PatQ]<br />
args fmt = concatMap (\(f,n) -> case f of<br />
L _ -> []<br />
_ -> [varP n]) $ zip fmt names<br />
where names = [ mkName $ 'x' : show i | i <- [0..] ]<br />
<br />
-- generate body of the function<br />
body :: [Format] -> ExpQ<br />
body fmt = foldr (\ e e' -> infixApp e [| (++) |] e') (last exps) (init exps)<br />
where exps = [ case f of<br />
L s -> stringE s<br />
D -> appE [| show |] (varE n)<br />
S -> varE n<br />
| (f,n) <- zip fmt names ]<br />
names = [ mkName $ 'x' : show i | i <- [0..] ]<br />
<br />
-- glue the argument list and body together into a lambda<br />
-- this is what gets spliced into the haskell code at the call<br />
-- site of "printf"<br />
printf :: String -> Q Exp<br />
printf format = lamE (args fmt) (body fmt)<br />
where fmt = tokenize format<br />
</haskell><br />
<br />
== Handling Options with Templates ==<br />
A common idiom for treating a set of options, e.g. from GetOpt, is to define a datatype with all the flags and using a list over this datatype:<br />
<br />
<haskell><br />
data Options = B1 | B2 | V Integer<br />
<br />
options = [B1, V 3]<br />
</haskell><br />
<br />
While it's simple testing if a Boolean flag is set (simply use "elem"), it's harder to check if an option with an argument is set. It's even more tedious writing helper-functions to obtain the value from such an option since you have to explicitely "un-V" each. Here, Template Haskell can be (ab)used to reduce this a bit. The following example provides the module "OptionsTH" which can be reused regardless of the constructors in "Options". Let's start with showing how we'd like to be able to program. Notice that the resulting lists need some more treatment e.g. through "foldl".<br />
<br />
Options.hs:<br />
<br />
<haskell><br />
module Main where<br />
<br />
import OptionsTH<br />
import Language.Haskell.TH.Syntax<br />
<br />
data Options = B1 | B2 | V Int | S String deriving (Eq, Read, Show)<br />
<br />
options = [B1, V 3]<br />
<br />
main = do<br />
print foo -- test if B1 set: [True,False]<br />
print bar -- test if V present, w/o value: [False,True]<br />
print baz -- get value of V if available: [Nothing,Just 3]<br />
<br />
foo :: [Bool]<br />
-- Query constructor B1 which takes no arguments<br />
foo = map $(getopt (THNoArg (mkArg "B1" 0))) options<br />
<br />
bar :: [Bool]<br />
-- V is a unary constructor. Let mkArg generate the required<br />
-- wildcard-pattern "V _".<br />
bar = map $(getopt (THNoArg (mkArg "V" 1))) options<br />
<br />
-- Can't use a wildcard here!<br />
baz :: [(Maybe Int)]<br />
baz = map $(getopt (THArg (conP "V" [varP "x"]))) options<br />
</haskell><br />
<br />
OptionsTH.hs<br />
<br />
<haskell><br />
module OptionsTH where<br />
<br />
import Language.Haskell.TH.Syntax<br />
<br />
-- datatype for querying options:<br />
-- NoArg: Not interested in value (also applies to Boolean flags)<br />
-- Arg: Grep value of unary(!) constructor<br />
data Args = THNoArg Pat | THArg Pat<br />
<br />
getopt :: Args -> ExpQ<br />
getopt (THNoArg pat) = lamE [varP "y"] (caseE (varE "y") [cons0, cons1])<br />
where<br />
cons0 = match pat (normalB [| True |]) []<br />
cons1 = match wildP (normalB [| False |]) []<br />
<br />
-- bind "var" for later use!<br />
getopt (THArg pat@(ConP _ [VarP var])) = lamE [varP "y"] (caseE (varE "y") [cons0, cons1])<br />
where<br />
cons0 = match pat (normalB (appE [|Just|] (varE var))) []<br />
cons1 = match wildP (normalB [|Nothing|]) []<br />
<br />
mkArg :: String -> Int -> Pat<br />
mkArg k c = conP k (replicate c wildP)<br />
</haskell><br />
<br />
While the example might look contrived for the Boolean options which could have been tested much easier, it shows how both types of arguments can be treated in a similar way.<br />
<br />
=== Limitations ===<br />
<tt>getopt (THArg pat)</tt> is only able to treat unary constructors. See the pattern-binding: It matches exactly a single VarP.<br />
<br />
=== Improvements ===<br />
The following reduces things even a bit more, though I still don't know if I like it. It only works since <tt>c</tt> is either 0 or 1.<br />
<br />
<haskell><br />
mkArg k c = conP k (replicate c (varP "x"))<br />
<br />
baz = map $(getopt (THArg (mkArg "V" 1)))<br />
</haskell><br />
-- VolkerStolz<br />
<br />
== Generic constructor for records ==<br />
<br />
I have a large number of record types like this, of different length:<br />
<br />
<haskell><br />
data PGD = PGD {<br />
pgdXUnitBase :: !Word8,<br />
pgdYUnitBase :: !Word8,<br />
pgdXLUnitsperUnitBase :: !Word16<br />
}<br />
</haskell><br />
<br />
Currently I use GHC's Binary module to read them from files; it can handle<br />
types like <tt>(Word8, (Word8, Word16))</tt>, but there was no easy way to generate<br />
the correct amount of "uncurry" calls for automatically grabbing each element.<br />
<br />
With Template Haskell, the instance declarations are now written as such:<br />
<br />
<haskell><br />
instance Binary PGD where<br />
get bh = do a <- get bh ; return $ $(constrRecord PGD) a<br />
</haskell><br />
<br />
Here the trick lies in constrRecord, which is defined as:<br />
<br />
<haskell><br />
constrRecord x = reify exp where<br />
reify = \(Just r) -> appE r $ conE $ last args<br />
exp = foldl (dot) uncur $ replicate terms uncur<br />
terms = ((length args) `div` 2) - 2<br />
dot x y = (Just $ infixE x (varE ".") y)<br />
uncur = (Just [|uncurry|])<br />
args = words . show $ typeOf x<br />
</haskell><br />
<br />
-- AutrijusTang<br />
<br />
== zipWithN ==<br />
<br />
Here $(zipn 3) = zipWith3 etc.<br />
<br />
<haskell><br />
import Language.Haskell.TH; import Control.Applicative; import Control.Monad<br />
<br />
zipn n = do<br />
vs <- replicateM n (newName "vs")<br />
[| \f -><br />
$(lamE (map varP vs)<br />
[| getZipList $<br />
$(foldl<br />
(\a b -> [| $a <*> $b |])<br />
[| pure f |]<br />
(map (\v -> [| ZipList $(varE v) |]) vs))<br />
|])<br />
|]<br />
</haskell><br />
<br />
== 'generic' zipWith ==<br />
A generalization of zipWith to almost any data. Demonstrates the ability to do dynamic binding with TH splices (note 'dyn').<br />
<br />
<haskell><br />
zipCons :: Name -> Int -> [String] -> ExpQ<br />
zipCons tyName ways functions = do<br />
let countFields :: Con -> (Name,Int)<br />
countFields x = case x of<br />
NormalC n (length -> fields) -> (n, fields)<br />
RecC n (length -> fields) -> (n,fields)<br />
InfixC _ n _ -> (n,2)<br />
ForallC _ _ ct -> countFields ct<br />
<br />
TyConI (DataD _ _ _ [countFields -> (c,n)] _) <- reify tyName<br />
when (n /= length functions) $ fail "wrong number of functions named"<br />
vs <- replicateM ways $ replicateM n $ newName "x"<br />
lamE (map (conP c . map varP) vs) $<br />
foldl (\con (vs,f) -><br />
con `appE`<br />
foldl appE<br />
(dyn f)<br />
(map varE vs))<br />
(conE c)<br />
(transpose vs `zip` functions)<br />
</haskell><br />
<br />
This example uses whichever '+' is in scope when the expression is spliced:<br />
<br />
<haskell><br />
:type $(zipCons ''(,,,) 2 (replicate 4 "+"))<br />
<br />
$(zipCons ''(,,,) 2 (replicate 4 "+"))<br />
:: (Num t, Num t1, Num t2, Num t3) =><br />
(t, t1, t2, t3) -> (t, t1, t2, t3) -> (t, t1, t2, t3)<br />
</haskell><br />
<br />
==[[Template haskell/Instance deriving example|Instance deriving example]]==<br />
An example using a 'deriving function' to generate a method instance <br />
per constructor of a type. The deriving function provides the body of the<br />
method.<br />
<br />
Note that this example assumes that the functions of the class take a parameter that is the same type as instance is parameterized with. <br />
<br />
The message [http://www.haskell.org/pipermail/template-haskell/2006-August/000581.html email message] contains the full source ([http://www.iist.unu.edu/~vs/haskell/TH_render.hs extracted file]).<br />
<br />
== [[Quasiquotation|QuasiQuoters]] ==<br />
New in ghc-6.10 is -XQuasiQuotes, which allows one to extend ghc's syntax from library code. Quite a few examples are given in [http://hackage.haskell.org/package/haskell-src-meta haskell-src-meta].<br />
<br />
=== Similarity with splices ===<br />
<br />
Quasiquoters used in expression contexts (those using the ''quoteExp'') behave to a first approximation like regular TH splices:<br />
<br />
<haskell><br />
simpleQQ = QuasiQuoter { quoteExp = stringE } -- in another module<br />
<br />
[$simpleQQ| a b c d |] == $(quoteExp simpleQQ " a b c d ")<br />
</haskell><br />
<br />
[[Category:Language extensions]]</div>Simonpjhttps://wiki.haskell.org/index.php?title=Template_Haskell&diff=41982Template Haskell2011-09-09T11:29:31Z<p>Simonpj: /* Tips and Tricks */</p>
<hr />
<div>'''[http://hackage.haskell.org/package/template-haskell Template Haskell]''' is a [[GHC]] extension to Haskell that adds compile-time metaprogramming facilities. The original design can be found here: http://research.microsoft.com/~simonpj/papers/meta-haskell/ . It is [http://haskell.cs.yale.edu/ghc/docs/6.2/html/users_guide/template-haskell.html included] in GHC version 6. <br />
<br />
This page hopes to be a more central and organized repository of TH related things.<br />
<br />
=What is Template Haskell?=<br />
Template Haskell is an extension to Haskell 98 that allows you to do type-safe compile-time meta-programming, with Haskell both as the manipulating language and the language being manipulated. <br />
<br />
Intuitively Template Haskell provides new language features that allow us to convert back and forth between concrete syntax, i.e. what you would type when you write normal Haskell code, and abstract syntax trees. These abstract syntax trees are represented using Haskell datatypes and, at compile time, they can be manipulated by Haskell code. This allows you to reify (convert from concrete syntax to an abstract syntax tree) some code, transform it and splice it back in (convert back again), or even to produce completely new code and splice that in, while the compiler is compiling your module. <br />
<br />
For email about Template Haskell, use the [http://haskell.org/mailman/listinfo/glasgow-haskell-users GHC users mailing list]. It's worth joining if you start to use TH.<br />
<br />
= Template Haskell specification =<br />
<br />
Template Haskell is only documented rather informally at the moment. Here are the main resources:<br />
<br />
* [http://www.haskell.org/ghc/docs/latest/html/users_guide/template-haskell.html The user manual section on Template Haskell]<br />
* [http://www.haskell.org/ghc/docs/latest/html/users_guide/template-haskell.html#th-quasiquotation The user manual section on quasi-quotation], which is closely related to Template Haskell.<br />
* [http://research.microsoft.com/~simonpj/papers/meta-haskell/ The original Template Haskell paper]<br />
* [http://research.microsoft.com/~simonpj/tmp/notes2.ps Notes on Template Haskell version 2], which describes changes since the original paper. Section 8 describes the difficulty with pattern splices, which are therefore not implemented.<br />
* [http://haskell.org/ghc/docs/7.0-latest/html/libraries/template-haskell-2.5.0.0/Language-Haskell-TH.html The Template Haskell API]<br />
<br />
= Template Haskell tutorials and papers =<br />
<br />
* Bulat's tutorials:<br />
** [http://docs.google.com/uc?id=0B4BgTwf_ng_TM2MxZjJjZjctMTQ0OS00YzcwLWE5N2QtMDI0YzE4NGUwZDM3 [formerly /bz/thdoc.htm]]<br />
** [http://docs.google.com/uc?id=0B4BgTwf_ng_TOGJkZjM4ZTUtNGY5My00ZThhLTllNDQtYzJjMWJiMzJhZjNj [formerly /bz/th3.htm]]<br />
<br />
: One reader said "These docs are *brilliant* ! Exactly what I need to get an understanding of TH."<br />
<br />
<small>(Note: These documents are from [http://www.archive.org the Wayback machine] because the originals disappeared. They're public documents on Google docs, which shouldn't require logging in. However, if you're asked to sign in to view them, you're running into a known Google bug. You can fix it by browsing to [http://www.google.com Google], presumably gaining a cookie in the process.)</small><br />
<br />
* Mark Snyder's Template Haskell chapter on the Software Generation and Configuration Report<br />
** http://nix.cs.uu.nl/dist/courses/sgc-report-unstable-latest/manual/chunk-chapter/templatehaskell.html<br />
<br />
* A very short tutorial to understand the basics in 10 Minutes.<br />
** http://www.hyperedsoftware.com/blog/entries/first-stab-th.html<br />
<br />
* GHC Template Haskell documentation<br />
** http://www.haskell.org/ghc/docs/7.0.2/html/users_guide/template-haskell.html<br />
<br />
* Papers about Template Haskell<br />
<br />
** Template metaprogramming for Haskell, by Tim Sheard and Simon Peyton Jones, Oct 2002. [[http://haskell.org/wikiupload/c/ca/Meta-haskell.ps ps]]<br />
** Template Haskell: A Report From The Field, by Ian Lynagh, May 2003. [[http://haskell.org/wikiupload/2/24/Template_Haskell-A_Report_From_The_Field.ps ps]]<br />
** Unrolling and Simplifying Expressions with Template Haskell, by Ian Lynagh, December 2002. [[http://haskell.org/wikiupload/e/ed/Template-Haskell-Utils.ps ps]]<br />
** Automatic skeletons in Template Haskell, by Kevin Hammond, Jost Berthold and Rita Loogen, June 2003. [[http://haskell.org/wikiupload/6/69/AutoSkelPPL03.pdf pdf]]<br />
** Optimising Embedded DSLs using Template Haskell, by Sean Seefried, Manuel Chakravarty, Gabriele Keller, March 2004. [[http://haskell.org/wikiupload/b/b5/Seefried04th-pan.pdf pdf]]<br />
** Typing Template Haskell: Soft Types, by Ian Lynagh, August 2004. [[http://haskell.org/wikiupload/7/72/Typing_Template_Haskell_Soft_Types.ps ps]]<br />
<br />
= Other useful resources =<br />
<br />
* [http://www.haskell.org/th/ The old Template Haskell web page]. Would someone feel like moving this material into the HaskellWiki?<br />
* Old and probably not too useful for most but maybe... http://www.cse.unsw.edu.au/~chak/haskell/ghc/comm/exts/th.html<br />
*[http://web.comlab.ox.ac.uk/oucl/work/ian.lynagh/Fraskell/ Fraskell documentation] & explanation of how Template Haskell is used to vastly speed it up.<br />
*[[Quasiquotation]]<br />
Feel free to update our Wikipedia entry<br />
http://en.wikipedia.org/wiki/Template_Haskell<br />
<br />
= Projects =<br />
<br />
What are you doing/planning to do/have done with Template Haskell?<br />
<br />
* The [http://www.ict.kth.se/org/ict/ecs/sam/projects/forsyde/www ForSyDe methodology] is currently implemented as a Haskell-based DSL which makes extensive use of Template Haskell.<br />
<br />
* I have written a primitive (untyped) binding to the Objective-C runtime system on Mac OS X. It needs just TH, no "stub files" are created, no seperate utilities are required. Initial snapshot is at http://www.kfunigraz.ac.at/imawww/thaller/wolfgang/HOC020103.tar.bz2 -- WolfgangThaller<br />
<br />
* I am writing Template Greencard - a reimplementation of GreenCard using TH. Many bits work out really nicely. A few bits didn't work so nicely - once I get some time to think, I'll try to persuade the TH folk to make some changes to fix some of these. -- AlastairReid<br />
<br />
* I'm writing Hacanon - a framework for automatic generation of C++ bindings. Read "automated Template Greencard for C++" (-: Darcs repo: http://www.ScannedInAvian.org/repos/hacanon - You'll need gccxml (http://www.gccxml.org/) to compile the exmples. - 27 Dec Lemmih.<br />
<br />
* Following other FFI tools developers, I see some future for Template HSFFIG, especially when it comes to autogenerate peek and poke methods for structures defined in C; may be useful for implementation of certain network protocols such as X11 where layout of messages is provided as C structure/union declaration. - 16 Dec 2005 DimitryGolubovsky<br />
<br />
* I am using Template Haskell as a mechanism to get parsed, typechecked code into an Ajax based Haskell Equational Reasoning tool [[Haskell Equational Reasoning Assistant]], as well as simplify the specification of equational relationships between pieces of code. There was a quicktime movie of the tool being used on http://www.gill-warbington.com/home/andy/share/hera1.html - AndyGill <br />
<br />
* I am working on functional metaprogramming techniques to enhance programming reliability and productivity, by reusing much of the existing compiler technology. Template Haskell is especially interesting for me because it permits to check size information of structures by the compiler, provided this information is available at compile time. This approach is especially appropriate for hardware designs, where the structures are fixed before the circuit starts operating. See our metaprogramming web page at http://www.infosun.fmi.uni-passau.de/cl/metaprog/ -- ChristophHerrmann(http://www.cs.st-and.ac.uk/~ch)<br />
<br />
* I am using Template Haskell to do type safe database access. I initially [http://www.nabble.com/Using-Template-Haskell-to-make-type-safe-database-access-td17027286.html proposed this on haskell-cafe]. I connect to the database at compile-time and let the database do SQL parsing and type inference. The result from parsing and type inference is used to build a type safe database query which can executed at run-time. [[MetaHDBC | You can find the project page here]] -- [mailto:mads_lindstroem@yahoo.dk Mads Lindstrøm]<br />
<br />
= Utilities =<br />
<br />
Helper functions, debugging functions, or more involved code e.g. a monadic fold algebra for TH.Syntax.<br />
<br />
* http://www.haskell.org/pipermail/template-haskell/2003-September/000176.html<br />
<br />
= Known Bugs =<br />
<br />
Take a look at the [http://hackage.haskell.org/trac/ghc/query?status=new&status=assigned&status=reopened&component=Template+Haskell&order=priority open bugs against Template Haskell] on the GHC bug tracker.<br />
<br />
= Wish list =<br />
<br />
Things that Ian Lynagh (Igloo) mentioned in his paper ''Template Haskell: A Report From The Field'' in May 2003 (available [http://www.haskell.org/th/papers.html here]), by section:<br />
<br />
* Section 2 (curses)<br />
** The ability to splice names (into "foreign import" declarations, in particular)<br />
** The ability to add things to the export list from a splice(?)<br />
** The ability to use things defined at the toplevel of a module from splices in that same module (would require multi-stage compilation, as opposed to the current approach of expanding splices during typechecking)<br />
<br />
* Section 3 (deriving instances of classes)<br />
** <strike>First-class reification</strike> (the <hask>reify</hask> function)<br />
** A way to discover whether a data constructor was defined infix or prefix (which is necessary to derive instances for <hask>Read</hask> and <hask>Show</hask> as outlined in [http://www.haskell.org/onlinereport/derived.html The Haskell 98 Report: Specification of Derived Instances]) (if there is a way, [http://www-users.cs.york.ac.uk/~ndm/derive/ Derive] seems ignorant of it)<br />
** Type/context splicing (in <hask>instance</hask> headers in particular)<br />
<br />
* Section 4 (printf)<br />
** He says something to the effect that a pattern-matching form of the quotation brackets would be cool if it was expressive enough to be useful, but that this would be hard. (Don't expect this anytime soon.)<br />
<br />
* Section 5 (fraskell)<br />
** Type information for quoted code (so that simplification can be done safely even with overloaded operations, like, oh, <hask>(+)</hask>)<br />
<br />
* Section 6 (pan)<br />
** Type info again, and strictnes info too (this one seems a bit pie-in-the-sky...)<br />
<br />
(Please leave the implemented ones here, but crossed off.)<br />
<br />
Any other features that may be nice, and TH projects you'd want to see.<br />
<br />
* A TH tutorial (mainly a distillation and update of ''Template Meta-programming in Haskell'' at this point)<br />
* <strike>Write Haddock documentation for the Template Haskell library (http://hackage.haskell.org/trac/ghc/ticket/1576).</strike><br />
* Make `reify` on a class return a list of the instances of that class (http://www.haskell.org/pipermail/template-haskell/2005-December/000503.html). (See also [http://hackage.haskell.org/trac/ghc/ticket/1577 GHC ticket #1577].)<br />
* A set of simple examples on this wiki page<br />
* A TH T-shirt with new logo to wear at conferences<br />
* (Long-term) Unify Language.Haskell.Syntax with Language.Haskell.TH.Syntax so there's just one way to do things (http://hackage.haskell.org/package/haskell-src-meta does a one-way translation, for haskell-src-exts)<br />
<br />
---------------<br />
<br />
= Tips and Tricks =<br />
<br />
== What to do when you can't splice that there ==<br />
<br />
When you try to splice something into the middle of a template and find that you just can't, instead of getting frustrated about it, why not use the template to see what it would look like in longhand? <br />
<br />
First, an excerpt from a module of my own. I, by the way, am SamB.<br />
<haskell><br />
{-# OPTIONS_GHC -fglasgow-exts -fth #-}<br />
<br />
module MMixMemory where<br />
<br />
import Data.Int<br />
import Data.Word<br />
<br />
class (Integral int, Integral word)<br />
=> SignConversion int word | int -> word, word -> int where<br />
<br />
toSigned :: word -> int<br />
toSigned = fromIntegral<br />
toUnsigned :: int -> word<br />
toUnsigned = fromIntegral<br />
<br />
</haskell><br />
<br />
Say I want to find out what I need to do to splice in the types for an instance declaration for the SignConversion class, so that I can declare instances for Int8 with Word8 through Int64 with Word64. So, I start up good-ol' GHCi and do the following:<br />
<br />
<haskell><br />
$ ghci -fth -fglasgow-exts<br />
Prelude> :l MMixMemory<br />
*MMixMemory> :m +Language.Haskell.TH.Syntax<br />
*MMixMemory Language.Haskell.TH.Syntax> runQ [d| instance SignConversion Int Word where |] >>= print<br />
[InstanceD [] (AppT (AppT (ConT MMixMemory.SignConversion) (ConT GHC.Base.Int)) (ConT GHC.Word.Word)) []]<br />
</haskell><br />
<br />
== What can <tt>reify</tt> see? ==<br />
<br />
== Why does <tt>runQ</tt> crash if I try to reify something? ==<br />
<br />
This program will fail with an error message when you run it:<br />
<haskell><br />
main = do info <- runQ (reify (mkName "Bool")) -- more hygenic is: (reify ''Bool)<br />
putStrLn (pprint info)<br />
</haskell><br />
Reason: <tt>reify</tt> consults the type environment, and that is not available at run-time. The type of <tt>reify</tt> is <br />
<haskell><br />
reify :: Quasi m => Q a -> m a<br />
</haskell><br />
The IO monad is a poor-man's instance of <tt>Quasi</tt>; it can allocate unique names and gather error messages, but it can't do <tt>reify</tt>. This error should really be caught statically.<br />
<br />
Instead, you can run the splice directly (ex. in ghci -XTemplateHaskell), as the following shows:<br />
<br />
<haskell><br />
GHCi> let tup = $(tupE $ take 4 $ cycle [ [| "hi" |] , [| 5 |] ])<br />
GHCi> :type tup<br />
tup :: ([Char], Integer, [Char], Integer)<br />
<br />
GHCi> tup<br />
("hi",5,"hi",5)<br />
<br />
GHCi> $(stringE . show =<< reify ''Int)<br />
"TyConI (DataD [] GHC.Types.Int [] [NormalC GHC.Types.I# [(NotStrict,ConT GHC.Prim.Int#)]] [])"<br />
</haskell><br />
<br />
Here's an [http://www.haskell.org/pipermail/glasgow-haskell-users/2006-August/010844.html email thread with more details].<br />
<br />
-----------------<br />
<br />
= Examples =<br />
== Tuples ==<br />
=== Select from a tuple ===<br />
<br />
An example to select an element from a tuple of arbitrary size. Taken from [http://www.haskell.org/th/papers/meta-haskell.ps this paper].<br />
<br />
Use like so:<br />
<br />
> $(sel 2 3) ('a','b','c')<br />
'b'<br />
> $(sel 3 4) ('a','b','c','d')<br />
'c'<br />
<br />
<br />
<haskell><br />
sel :: Int -> Int -> ExpQ<br />
sel i n = [| \x -> $(caseE [| x |] [alt]) |]<br />
where alt :: MatchQ<br />
alt = match pat (normalB rhs) []<br />
<br />
pat :: Pat<br />
pat = tupP (map varP as)<br />
<br />
rhs :: ExpQ<br />
rhs = varE(as !! (i -1)) -- !! is 0 based<br />
<br />
as :: [String]<br />
as = ["a" ++ show i | i <- [1..n] ]<br />
</haskell><br />
<br />
Alternately:<br />
<br />
<haskell><br />
sel' i n = lamE [pat] rhs<br />
where pat = tupP (map varP as)<br />
rhs = varE (as !! (i - 1))<br />
as = [ "a" ++ show j | j <- [1..n] ]<br />
</haskell><br />
<br />
=== Apply a function to the n'th element ===<br />
<br />
<haskell><br />
tmap i n = do<br />
f <- newName "f"<br />
as <- replicateM n (newName "a")<br />
lamE [varP f, tupP (map varP as)] $<br />
tupE [ if i == i'<br />
then [| $(varE f) $a |]<br />
else a<br />
| (a,i') <- map varE as `zip` [1..] ]<br />
</haskell><br />
<br />
Then tmap can be called as:<br />
<br />
> $(tmap 3 4) (+ 1) (1,2,3,4)<br />
(1,2,4,4)<br />
<br />
=== Convert the first n elements of a list to a tuple ===<br />
<br />
This example creates a tuple by extracting elemnts from a list. Taken from<br />
[http://www.xoltar.org/2003/aug/13/templateHaskellTupleSample.html www.xoltar.org]<br />
<br />
Use like so:<br />
<br />
> $(tuple 3) [1,2,3,4,5]<br />
(1,2,3)<br />
> $(tuple 2) [1,2]<br />
(1,2)<br />
<br />
<haskell><br />
tuple :: Int -> ExpQ<br />
tuple n = [|\list -> $(tupE (exprs [|list|])) |]<br />
where<br />
exprs list = [infixE (Just (list))<br />
(varE "!!")<br />
(Just (litE $ integerL (toInteger num)))<br />
| num <- [0..(n - 1)]]<br />
</haskell><br />
<br />
An alternative that has more informative errors (a failing pattern match failures give an exact location):<br />
<br />
<haskell><br />
tuple :: Int -> ExpQ<br />
tuple n = do<br />
ns <- replicateM n (newName "x")<br />
lamE [foldr (\x y -> conP '(:) [varP x,y]) wildP ns] (tupE $ map varE ns)<br />
</haskell><br />
<br />
=== Un-nest tuples ===<br />
Convert nested tuples like (a,(b,(c,()))) into (a,b,c) given the length to generate.<br />
<br />
<haskell><br />
unNest n = do<br />
vs <- replicateM n (newName "x")<br />
lamE [foldr (\a b -> tupP [varP a , b])<br />
(conP '() [])<br />
vs]<br />
(tupE (map varE vs))<br />
</haskell><br />
<br />
<br />
<br />
== [[Template Haskell/Marshall Data|Marshall a datatype to and from Dynamic]] ==<br />
This approach is an example of using template haskell to delay typechecking<br />
to be able to abstract out the repeated calls to fromDynamic:<br />
<br />
<haskell><br />
data T = T Int String Double<br />
<br />
toT :: [Dynamic] -> Maybe T<br />
toT [a,b,c] = do<br />
a' <- fromDynamic a<br />
b' <- fromDynamic b<br />
c' <- fromDynamic c<br />
return (T a' b' c')<br />
toT _ = Nothing<br />
</haskell><br />
<br />
== Printf ==<br />
Build it using a command similar to:<br />
<br />
ghc --make Main.hs -o main<br />
<br />
Main.hs:<br />
<br />
<haskell><br />
{-# LANGUAGE TemplateHaskell #-}<br />
<br />
-- Import our template "printf"<br />
import PrintF (printf)<br />
<br />
-- The splice operator $ takes the Haskell source code<br />
-- generated at compile time by "printf" and splices it into<br />
-- the argument of "putStrLn".<br />
main = do<br />
putStrLn $ $(printf "Hello %s %%x%% %d %%x%%") "World" 12<br />
</haskell><br />
<br />
PrintF.hs:<br />
<br />
<haskell><br />
{-# LANGUAGE TemplateHaskell #-}<br />
module PrintF where<br />
<br />
-- NB: printf needs to be in a separate module to the one where<br />
-- you intend to use it.<br />
<br />
-- Import some Template Haskell syntax<br />
import Language.Haskell.TH<br />
<br />
-- Possible string tokens: %d %s and literal strings<br />
data Format = D | S | L String<br />
deriving Show<br />
<br />
-- a poor man's tokenizer<br />
tokenize :: String -> [Format]<br />
tokenize [] = []<br />
tokenize ('%':c:rest) | c == 'd' = D : tokenize rest<br />
| c == 's' = S : tokenize rest<br />
tokenize (s:str) = L (s:p) : tokenize rest -- so we don't get stuck on weird '%'<br />
where (p,rest) = span (/= '%') str<br />
<br />
-- generate argument list for the function<br />
args :: [Format] -> [PatQ]<br />
args fmt = concatMap (\(f,n) -> case f of<br />
L _ -> []<br />
_ -> [varP n]) $ zip fmt names<br />
where names = [ mkName $ 'x' : show i | i <- [0..] ]<br />
<br />
-- generate body of the function<br />
body :: [Format] -> ExpQ<br />
body fmt = foldr (\ e e' -> infixApp e [| (++) |] e') (last exps) (init exps)<br />
where exps = [ case f of<br />
L s -> stringE s<br />
D -> appE [| show |] (varE n)<br />
S -> varE n<br />
| (f,n) <- zip fmt names ]<br />
names = [ mkName $ 'x' : show i | i <- [0..] ]<br />
<br />
-- glue the argument list and body together into a lambda<br />
-- this is what gets spliced into the haskell code at the call<br />
-- site of "printf"<br />
printf :: String -> Q Exp<br />
printf format = lamE (args fmt) (body fmt)<br />
where fmt = tokenize format<br />
</haskell><br />
<br />
== Handling Options with Templates ==<br />
A common idiom for treating a set of options, e.g. from GetOpt, is to define a datatype with all the flags and using a list over this datatype:<br />
<br />
<haskell><br />
data Options = B1 | B2 | V Integer<br />
<br />
options = [B1, V 3]<br />
</haskell><br />
<br />
While it's simple testing if a Boolean flag is set (simply use "elem"), it's harder to check if an option with an argument is set. It's even more tedious writing helper-functions to obtain the value from such an option since you have to explicitely "un-V" each. Here, Template Haskell can be (ab)used to reduce this a bit. The following example provides the module "OptionsTH" which can be reused regardless of the constructors in "Options". Let's start with showing how we'd like to be able to program. Notice that the resulting lists need some more treatment e.g. through "foldl".<br />
<br />
Options.hs:<br />
<br />
<haskell><br />
module Main where<br />
<br />
import OptionsTH<br />
import Language.Haskell.TH.Syntax<br />
<br />
data Options = B1 | B2 | V Int | S String deriving (Eq, Read, Show)<br />
<br />
options = [B1, V 3]<br />
<br />
main = do<br />
print foo -- test if B1 set: [True,False]<br />
print bar -- test if V present, w/o value: [False,True]<br />
print baz -- get value of V if available: [Nothing,Just 3]<br />
<br />
foo :: [Bool]<br />
-- Query constructor B1 which takes no arguments<br />
foo = map $(getopt (THNoArg (mkArg "B1" 0))) options<br />
<br />
bar :: [Bool]<br />
-- V is a unary constructor. Let mkArg generate the required<br />
-- wildcard-pattern "V _".<br />
bar = map $(getopt (THNoArg (mkArg "V" 1))) options<br />
<br />
-- Can't use a wildcard here!<br />
baz :: [(Maybe Int)]<br />
baz = map $(getopt (THArg (conP "V" [varP "x"]))) options<br />
</haskell><br />
<br />
OptionsTH.hs<br />
<br />
<haskell><br />
module OptionsTH where<br />
<br />
import Language.Haskell.TH.Syntax<br />
<br />
-- datatype for querying options:<br />
-- NoArg: Not interested in value (also applies to Boolean flags)<br />
-- Arg: Grep value of unary(!) constructor<br />
data Args = THNoArg Pat | THArg Pat<br />
<br />
getopt :: Args -> ExpQ<br />
getopt (THNoArg pat) = lamE [varP "y"] (caseE (varE "y") [cons0, cons1])<br />
where<br />
cons0 = match pat (normalB [| True |]) []<br />
cons1 = match wildP (normalB [| False |]) []<br />
<br />
-- bind "var" for later use!<br />
getopt (THArg pat@(ConP _ [VarP var])) = lamE [varP "y"] (caseE (varE "y") [cons0, cons1])<br />
where<br />
cons0 = match pat (normalB (appE [|Just|] (varE var))) []<br />
cons1 = match wildP (normalB [|Nothing|]) []<br />
<br />
mkArg :: String -> Int -> Pat<br />
mkArg k c = conP k (replicate c wildP)<br />
</haskell><br />
<br />
While the example might look contrived for the Boolean options which could have been tested much easier, it shows how both types of arguments can be treated in a similar way.<br />
<br />
=== Limitations ===<br />
<tt>getopt (THArg pat)</tt> is only able to treat unary constructors. See the pattern-binding: It matches exactly a single VarP.<br />
<br />
=== Improvements ===<br />
The following reduces things even a bit more, though I still don't know if I like it. It only works since <tt>c</tt> is either 0 or 1.<br />
<br />
<haskell><br />
mkArg k c = conP k (replicate c (varP "x"))<br />
<br />
baz = map $(getopt (THArg (mkArg "V" 1)))<br />
</haskell><br />
-- VolkerStolz<br />
<br />
== Generic constructor for records ==<br />
<br />
I have a large number of record types like this, of different length:<br />
<br />
<haskell><br />
data PGD = PGD {<br />
pgdXUnitBase :: !Word8,<br />
pgdYUnitBase :: !Word8,<br />
pgdXLUnitsperUnitBase :: !Word16<br />
}<br />
</haskell><br />
<br />
Currently I use GHC's Binary module to read them from files; it can handle<br />
types like <tt>(Word8, (Word8, Word16))</tt>, but there was no easy way to generate<br />
the correct amount of "uncurry" calls for automatically grabbing each element.<br />
<br />
With Template Haskell, the instance declarations are now written as such:<br />
<br />
<haskell><br />
instance Binary PGD where<br />
get bh = do a <- get bh ; return $ $(constrRecord PGD) a<br />
</haskell><br />
<br />
Here the trick lies in constrRecord, which is defined as:<br />
<br />
<haskell><br />
constrRecord x = reify exp where<br />
reify = \(Just r) -> appE r $ conE $ last args<br />
exp = foldl (dot) uncur $ replicate terms uncur<br />
terms = ((length args) `div` 2) - 2<br />
dot x y = (Just $ infixE x (varE ".") y)<br />
uncur = (Just [|uncurry|])<br />
args = words . show $ typeOf x<br />
</haskell><br />
<br />
-- AutrijusTang<br />
<br />
== zipWithN ==<br />
<br />
Here $(zipn 3) = zipWith3 etc.<br />
<br />
<haskell><br />
import Language.Haskell.TH; import Control.Applicative; import Control.Monad<br />
<br />
zipn n = do<br />
vs <- replicateM n (newName "vs")<br />
[| \f -><br />
$(lamE (map varP vs)<br />
[| getZipList $<br />
$(foldl<br />
(\a b -> [| $a <*> $b |])<br />
[| pure f |]<br />
(map (\v -> [| ZipList $(varE v) |]) vs))<br />
|])<br />
|]<br />
</haskell><br />
<br />
== 'generic' zipWith ==<br />
A generalization of zipWith to almost any data. Demonstrates the ability to do dynamic binding with TH splices (note 'dyn').<br />
<br />
<haskell><br />
zipCons :: Name -> Int -> [String] -> ExpQ<br />
zipCons tyName ways functions = do<br />
let countFields :: Con -> (Name,Int)<br />
countFields x = case x of<br />
NormalC n (length -> fields) -> (n, fields)<br />
RecC n (length -> fields) -> (n,fields)<br />
InfixC _ n _ -> (n,2)<br />
ForallC _ _ ct -> countFields ct<br />
<br />
TyConI (DataD _ _ _ [countFields -> (c,n)] _) <- reify tyName<br />
when (n /= length functions) $ fail "wrong number of functions named"<br />
vs <- replicateM ways $ replicateM n $ newName "x"<br />
lamE (map (conP c . map varP) vs) $<br />
foldl (\con (vs,f) -><br />
con `appE`<br />
foldl appE<br />
(dyn f)<br />
(map varE vs))<br />
(conE c)<br />
(transpose vs `zip` functions)<br />
</haskell><br />
<br />
This example uses whichever '+' is in scope when the expression is spliced:<br />
<br />
<haskell><br />
:type $(zipCons ''(,,,) 2 (replicate 4 "+"))<br />
<br />
$(zipCons ''(,,,) 2 (replicate 4 "+"))<br />
:: (Num t, Num t1, Num t2, Num t3) =><br />
(t, t1, t2, t3) -> (t, t1, t2, t3) -> (t, t1, t2, t3)<br />
</haskell><br />
<br />
==[[Template haskell/Instance deriving example|Instance deriving example]]==<br />
An example using a 'deriving function' to generate a method instance <br />
per constructor of a type. The deriving function provides the body of the<br />
method.<br />
<br />
Note that this example assumes that the functions of the class take a parameter that is the same type as instance is parameterized with. <br />
<br />
The message [http://www.haskell.org/pipermail/template-haskell/2006-August/000581.html email message] contains the full source ([http://www.iist.unu.edu/~vs/haskell/TH_render.hs extracted file]).<br />
<br />
== [[Quasiquotation|QuasiQuoters]] ==<br />
New in ghc-6.10 is -XQuasiQuotes, which allows one to extend ghc's syntax from library code. Quite a few examples are given in [http://hackage.haskell.org/package/haskell-src-meta haskell-src-meta].<br />
<br />
=== Similarity with splices ===<br />
<br />
Quasiquoters used in expression contexts (those using the ''quoteExp'') behave to a first approximation like regular TH splices:<br />
<br />
<haskell><br />
simpleQQ = QuasiQuoter { quoteExp = stringE } -- in another module<br />
<br />
[$simpleQQ| a b c d |] == $(quoteExp simpleQQ " a b c d ")<br />
</haskell><br />
<br />
[[Category:Language extensions]]</div>Simonpjhttps://wiki.haskell.org/index.php?title=Library_submissions&diff=41435Library submissions2011-08-04T20:23:40Z<p>Simonpj: /* The Core Libraries */</p>
<hr />
<div>This page describes the process for maintaining the <br />
'''Core libraries'''. The core libraries are a subset of the packages in the<br />
Haskell Platform, and define basic APIs that are expected to be<br />
available in any Haskell implementation. They are listed under "The Core Libraries" below.<br />
<br />
Non-core libraries are, of course, managed by their own authors/maintainers (named in their .cabal file), using whatever policies those maintainers see fit. [Note: arguably the policies below might usefully be applied to all libraries embodied in the Haskell Platform, but that is a question for the HP team.]<br />
<br />
= General principles =<br />
<br />
* Each core package has a named maintainer, or small group of maintainers, who have commit access to the package. <br />
<br />
* Third parties are encouraged to make proposals for changes, both to the library API and its implementation, by sending the proposal to the maintainer (CC'ing the libraries mailing list).<br />
<br />
* The maintainer is trusted to decide what changes to make to the package, and when. They are strongly encouraged to follow the guidance below, but the general principle is: the community offers opinions, but the maintainers decide.<br />
<br />
<br />
= Responsiveness =<br />
<br />
* Third parties submitting proposals to the maintainer of a library can expect a timely and thoughtful response. <br />
* The more effort the proposer invests (for example, by constructing a patch rather than making an off-the-cuff suggestion) the more consideration s/he can reasonably expect.<br />
* Proposals that have widespread support, and are accompanied by patches (preferably with tests and documentation), should normally be accepted by the maintainer. <br />
* It is up to the maintainer to decide what "widespread" means; in particular, it does not always mean "a majority of those who responded". The majority-responder story is vulnerable to selection bias; e.g. 7 people (out of a client base of hundreds) say "add this function" but the maintainer thinks it will make the interface incrementally more complicated without sufficient benefit.<br />
* Where there is significant work involved in implementing a proposal, it is reasonable for a maintainer to ask for a patch. The principle is that maintainers are not obliged to do the work of implementing a proposal, even if it does enjoy wide support. For more substantial changes, it makes sense to develop the implementation in dialogue with the maintainer.<br />
<br />
= Guidance for proposers =<br />
<br />
A "proposal" can be anything from a one-sentence suggestion to a fully-implemented, tested, and documented patch.<br />
However, the more substantial the proposal the more attention you can expect. The process is this:<br />
<br />
* Send your proposal by email to the maintainer, with a copy to the libraries@haskell.org mailing list (which you need to [http://www.haskell.org/mailman/listinfo/libraries subscribe] to before posting).<br />
<br />
* Set a deadline for discussion (no less than two weeks), and act as chair/moderator for the discussion. <br />
<br />
* At the end of the discussion period, summarise your understanding of the consensus (or lack thereof), including a link to the thread in the mailing list archives, and send the summary to the maintainer for decision. The deadline gives you a moment to summarise the debate and hand over to the maintainer. It isn't a deadline for the maintainer to decide; for example he or she may seek more discussion first. <br />
<br />
* If the decision is positive, [http://hackage.haskell.org/trac/ghc/newticket create a ticket] on the GHC trac. The description of the ticket can summarise the proposal and link to the mail thread. Further discussion and implementation patches can be attached to the ticket, and the ticket helps the maintainer to keep track of what is on the go. (Obviously if the maintainer prefers some other mechanism, follow his or her guidance.)<br />
<br />
* For non-trivial changes the maintainer may ask for a patch. You may create the patch up front, and make it part of your proposal; or you may want to have some discussion about the design first, and only then roll up your sleeves to do the implementation; and for bigger jobs you may want to wait until the maintainer agrees in principle with the change.<br />
<br />
Here are desirable properties for a proposal and its implementation. The more of these properties your proposal or patch has, the more likely it is that the maintainer will adopt your idea. After all, to adopt it the maintainter will have to do whatever tasks you didn't do.<br />
<br />
* '''Description'''. A good proposal says clearly ''what'' you propose, ''why'' it is a good idea, and what its consequences would be.<br />
* '''Patch'''. Use <tt>darcs record</tt> or <tt>git commit</tt> (depending on what sort of repo the library lives in) to create it. Save the patch to a file, using <tt>darcs send --output</tt> or <tt>git format-patch</tt>. Make your changes against a copy of the master branch of the relevant library, and make sure it compiles.<br />
* '''Portability'''. Good code is portable. In particular, try to ensure the code runs in Hugs and GHC, and on Windows and Linux.<br />
* '''Style'''. Good code follows the conventions in the library you are modifying.<br />
* '''Documentation'''. Good code includes valid [http://haskell.org/haddock Haddock] documentation.<br />
* '''Tests'''. Good patches have suitable tests for the library's testsuite.<br />
<br />
= Guidance for maintainers =<br />
<br />
The principle is that we '''trust the maintainer''' to behave sensibly. The guidelines below are just that: guidelines, not rules. Still, the core libraries are used by many, many people, so maintainers should make every effort not to mess them up by accident. <br />
<br />
* '''API changes should be discussed''' on the libraries mailing list prior to making the change, even if the maintainer is the proposer. The maintainer still has ultimate say in what changes are made, but the community should have the opportunity to comment on changes. However, unanimity (or even a majority) is not required.<br />
<br />
* '''Every API change should be described precisely in the commit log.''' The commit logs should be sent to a public mailing list, or otherwise made easily available (e.g. via github), so that the community can keep an eye on changes and comment.<br />
<br />
* '''Backwards compatibility''' is important to many users. API changes are expected to retain backwards compatibility wherever possible. However, from time to time we may decide to have major revisions which are explicitly not backwards compatible; in these cases we may try to make the previous version of the package available concurrently, as in the base-3/base-4 switchover.<br />
<br />
* You don't need to consult the community for '''purely internal changes'''; i.e. changes that do not affect the library's clients.<br />
<br />
* Changes that simply '''widen the API by adding new functions''' are a bit of a grey area. It's better to consult the community, because there may be useful feedback about (say) the order of arguments, or the name of the function, or whatnot. On the other hand few clients will actually break if you add a new function to the API. Use your judgment.<br />
<br />
Libraries maintained by the GHC team are subject to the GHC validation policy - patches will be tested for validation before committing. Those packages not maintained by the GHC team will probably have a GHC lagging mirror repository that is subject to validation.<br />
<br />
= The Core Libraries =<br />
<br />
The following packages constitute the core libraries:<br />
<br />
{| border="1"<br />
! Package !! Maintainer<br />
|-<br />
| [http://hackage.haskell.org/package/array array] || GHC HQ<br />
|-<br />
| [http://hackage.haskell.org/package/base base] || GHC HQ<br />
|-<br />
| [http://hackage.haskell.org/package/containers containers] || Johan Tibell and Milan Straka<br />
|-<br />
| [http://hackage.haskell.org/package/deepseq deepseq] || Simon Marlow<br />
|-<br />
| [http://hackage.haskell.org/package/directory directory] || GHC HQ<br />
|-<br />
| [http://hackage.haskell.org/package/extensible-exceptions extensible-exceptions] || GHC HQ <br />
|-<br />
| [http://hackage.haskell.org/package/ghc-prim ghc-prim] || GHC HQ <br />
|-<br />
| [http://hackage.haskell.org/package/hpc hpc] || Andy Gill <br />
|-<br />
| [http://hackage.haskell.org/package/mtl mtl] || Edward Kmett<br />
|-<br />
| [http://hackage.haskell.org/package/parallel parallel] || Simon Marlow<br />
|-<br />
| [http://hackage.haskell.org/package/pretty pretty] || David Terei<br />
|-<br />
| [http://hackage.haskell.org/package/process process] || GHC HQ <br />
|-<br />
| [http://hackage.haskell.org/package/random random] || Ryan Newton<br />
|-<br />
| [http://hackage.haskell.org/package/template-haskell template-haskell] || GHC HQ<br />
|-<br />
| [http://hackage.haskell.org/package/unix unix] || GHC HQ<br />
|-<br />
| [http://hackage.haskell.org/package/Win32 Win32] || Bryan O'Sullivan<br />
|-<br />
| [http://hackage.haskell.org/package/xhtml xhtml] || Chris Dornan<br />
|}<br />
<br />
The maintainer "GHC HQ" means Simon Marlow, Simon Peyton Jones, and Ian Lynagh. Daniel Fischer has taken responsibility for numeric stuff. Email cvs-ghc@haskell.org<br />
<br />
The following packages match the appropriate language standard, and as such cannot change independently. The code is maintained by the GHC team.<br />
<br />
{| border="1"<br />
|-<br />
| [http://hackage.haskell.org/package/haskell2010 haskell2010] || GHC HQ<br />
|-<br />
| [http://hackage.haskell.org/package/haskell98 haskell98] || GHC HQ<br />
|}<br />
<br />
These packages are maintained only for backward compatibility, and are not expected to undergo API changes in the future. <br />
<br />
{| border="1"<br />
|-<br />
| [http://hackage.haskell.org/package/old-locale old-locale] || GHC HQ <br />
|-<br />
| [http://hackage.haskell.org/package/old-time old-time] || GHC HQ <br />
|}<br />
<br />
= See also =<br />
<br />
* [http://hackage.haskell.org/trac/ghc/wiki/WorkingConventions GHC Working Conventions], including guidelines for submitting patches via darcs.<br />
* [http://haskell.org/haskellwiki/Category:Style Notes on programming style]<br />
<br />
[[Category:Community]]<br />
[[Category:Proposals| ]]</div>Simonpjhttps://wiki.haskell.org/index.php?title=Library_submissions&diff=41434Library submissions2011-08-04T20:23:05Z<p>Simonpj: /* The Core Libraries */</p>
<hr />
<div>This page describes the process for maintaining the <br />
'''Core libraries'''. The core libraries are a subset of the packages in the<br />
Haskell Platform, and define basic APIs that are expected to be<br />
available in any Haskell implementation. They are listed under "The Core Libraries" below.<br />
<br />
Non-core libraries are, of course, managed by their own authors/maintainers (named in their .cabal file), using whatever policies those maintainers see fit. [Note: arguably the policies below might usefully be applied to all libraries embodied in the Haskell Platform, but that is a question for the HP team.]<br />
<br />
= General principles =<br />
<br />
* Each core package has a named maintainer, or small group of maintainers, who have commit access to the package. <br />
<br />
* Third parties are encouraged to make proposals for changes, both to the library API and its implementation, by sending the proposal to the maintainer (CC'ing the libraries mailing list).<br />
<br />
* The maintainer is trusted to decide what changes to make to the package, and when. They are strongly encouraged to follow the guidance below, but the general principle is: the community offers opinions, but the maintainers decide.<br />
<br />
<br />
= Responsiveness =<br />
<br />
* Third parties submitting proposals to the maintainer of a library can expect a timely and thoughtful response. <br />
* The more effort the proposer invests (for example, by constructing a patch rather than making an off-the-cuff suggestion) the more consideration s/he can reasonably expect.<br />
* Proposals that have widespread support, and are accompanied by patches (preferably with tests and documentation), should normally be accepted by the maintainer. <br />
* It is up to the maintainer to decide what "widespread" means; in particular, it does not always mean "a majority of those who responded". The majority-responder story is vulnerable to selection bias; e.g. 7 people (out of a client base of hundreds) say "add this function" but the maintainer thinks it will make the interface incrementally more complicated without sufficient benefit.<br />
* Where there is significant work involved in implementing a proposal, it is reasonable for a maintainer to ask for a patch. The principle is that maintainers are not obliged to do the work of implementing a proposal, even if it does enjoy wide support. For more substantial changes, it makes sense to develop the implementation in dialogue with the maintainer.<br />
<br />
= Guidance for proposers =<br />
<br />
A "proposal" can be anything from a one-sentence suggestion to a fully-implemented, tested, and documented patch.<br />
However, the more substantial the proposal the more attention you can expect. The process is this:<br />
<br />
* Send your proposal by email to the maintainer, with a copy to the libraries@haskell.org mailing list (which you need to [http://www.haskell.org/mailman/listinfo/libraries subscribe] to before posting).<br />
<br />
* Set a deadline for discussion (no less than two weeks), and act as chair/moderator for the discussion. <br />
<br />
* At the end of the discussion period, summarise your understanding of the consensus (or lack thereof), including a link to the thread in the mailing list archives, and send the summary to the maintainer for decision. The deadline gives you a moment to summarise the debate and hand over to the maintainer. It isn't a deadline for the maintainer to decide; for example he or she may seek more discussion first. <br />
<br />
* If the decision is positive, [http://hackage.haskell.org/trac/ghc/newticket create a ticket] on the GHC trac. The description of the ticket can summarise the proposal and link to the mail thread. Further discussion and implementation patches can be attached to the ticket, and the ticket helps the maintainer to keep track of what is on the go. (Obviously if the maintainer prefers some other mechanism, follow his or her guidance.)<br />
<br />
* For non-trivial changes the maintainer may ask for a patch. You may create the patch up front, and make it part of your proposal; or you may want to have some discussion about the design first, and only then roll up your sleeves to do the implementation; and for bigger jobs you may want to wait until the maintainer agrees in principle with the change.<br />
<br />
Here are desirable properties for a proposal and its implementation. The more of these properties your proposal or patch has, the more likely it is that the maintainer will adopt your idea. After all, to adopt it the maintainter will have to do whatever tasks you didn't do.<br />
<br />
* '''Description'''. A good proposal says clearly ''what'' you propose, ''why'' it is a good idea, and what its consequences would be.<br />
* '''Patch'''. Use <tt>darcs record</tt> or <tt>git commit</tt> (depending on what sort of repo the library lives in) to create it. Save the patch to a file, using <tt>darcs send --output</tt> or <tt>git format-patch</tt>. Make your changes against a copy of the master branch of the relevant library, and make sure it compiles.<br />
* '''Portability'''. Good code is portable. In particular, try to ensure the code runs in Hugs and GHC, and on Windows and Linux.<br />
* '''Style'''. Good code follows the conventions in the library you are modifying.<br />
* '''Documentation'''. Good code includes valid [http://haskell.org/haddock Haddock] documentation.<br />
* '''Tests'''. Good patches have suitable tests for the library's testsuite.<br />
<br />
= Guidance for maintainers =<br />
<br />
The principle is that we '''trust the maintainer''' to behave sensibly. The guidelines below are just that: guidelines, not rules. Still, the core libraries are used by many, many people, so maintainers should make every effort not to mess them up by accident. <br />
<br />
* '''API changes should be discussed''' on the libraries mailing list prior to making the change, even if the maintainer is the proposer. The maintainer still has ultimate say in what changes are made, but the community should have the opportunity to comment on changes. However, unanimity (or even a majority) is not required.<br />
<br />
* '''Every API change should be described precisely in the commit log.''' The commit logs should be sent to a public mailing list, or otherwise made easily available (e.g. via github), so that the community can keep an eye on changes and comment.<br />
<br />
* '''Backwards compatibility''' is important to many users. API changes are expected to retain backwards compatibility wherever possible. However, from time to time we may decide to have major revisions which are explicitly not backwards compatible; in these cases we may try to make the previous version of the package available concurrently, as in the base-3/base-4 switchover.<br />
<br />
* You don't need to consult the community for '''purely internal changes'''; i.e. changes that do not affect the library's clients.<br />
<br />
* Changes that simply '''widen the API by adding new functions''' are a bit of a grey area. It's better to consult the community, because there may be useful feedback about (say) the order of arguments, or the name of the function, or whatnot. On the other hand few clients will actually break if you add a new function to the API. Use your judgment.<br />
<br />
Libraries maintained by the GHC team are subject to the GHC validation policy - patches will be tested for validation before committing. Those packages not maintained by the GHC team will probably have a GHC lagging mirror repository that is subject to validation.<br />
<br />
= The Core Libraries =<br />
<br />
The following packages constitute the core libraries:<br />
<br />
{| border="1"<br />
! Package !! Maintainer<br />
|-<br />
| [http://hackage.haskell.org/package/array array] || GHC HQ<br />
|-<br />
| [http://hackage.haskell.org/package/base base] || GHC HQ<br />
|-<br />
| [http://hackage.haskell.org/package/containers containers] || Johan Tibell and Milan Straka<br />
|-<br />
| [http://hackage.haskell.org/package/deepseq deepseq] || Simon Marlow<br />
|-<br />
| [http://hackage.haskell.org/package/directory directory] || GHC HQ<br />
|-<br />
| [http://hackage.haskell.org/package/extensible-exceptions extensible-exceptions] || GHC HQ <br />
|-<br />
| [http://hackage.haskell.org/package/ghc-prim ghc-prim] || GHC HQ <br />
|-<br />
| [http://hackage.haskell.org/package/hpc hpc] || Andy Gill <br />
|-<br />
| [http://hackage.haskell.org/package/mtl mtl] || Edward Kmett<br />
|-<br />
| [http://hackage.haskell.org/package/parallel parallel] || Simon Marlow<br />
|-<br />
| [http://hackage.haskell.org/package/pretty pretty] || David Terei<br />
|-<br />
| [http://hackage.haskell.org/package/process process] || GHC HQ <br />
|-<br />
| [http://hackage.haskell.org/package/random random] || Ryan Newton<br />
|-<br />
| [http://hackage.haskell.org/package/template-haskell template-haskell] || GHC HQ<br />
|-<br />
| [http://hackage.haskell.org/package/unix unix] || GHC HQ<br />
|-<br />
| [http://hackage.haskell.org/package/Win32 Win32] || Bryan O'Sullivan<br />
|-<br />
| [http://hackage.haskell.org/package/xhtml xhtml] || Chris Dornan<br />
|}<br />
<br />
* The maintainer "GHC HQ" means Simon Marlow, Simon Peyton Jones, and Ian Lynagh. Daniel Fischer has taken responsibility for numeric stuff. Email cvs-ghc@haskell.org<br />
* "Volunteer needed" means that GHC HQ is the default maintainer, but that we'd like someone else to volunteer please!<br />
<br />
The following packages match the appropriate language standard, and as such cannot change independently. The code is maintained by the GHC team.<br />
<br />
{| border="1"<br />
|-<br />
| [http://hackage.haskell.org/package/haskell2010 haskell2010] || GHC HQ<br />
|-<br />
| [http://hackage.haskell.org/package/haskell98 haskell98] || GHC HQ<br />
|}<br />
<br />
These packages are maintained only for backward compatibility, and are not expected to undergo API changes in the future. <br />
<br />
{| border="1"<br />
|-<br />
| [http://hackage.haskell.org/package/old-locale old-locale] || GHC HQ <br />
|-<br />
| [http://hackage.haskell.org/package/old-time old-time] || GHC HQ <br />
|}<br />
<br />
= See also =<br />
<br />
* [http://hackage.haskell.org/trac/ghc/wiki/WorkingConventions GHC Working Conventions], including guidelines for submitting patches via darcs.<br />
* [http://haskell.org/haskellwiki/Category:Style Notes on programming style]<br />
<br />
[[Category:Community]]<br />
[[Category:Proposals| ]]</div>Simonpjhttps://wiki.haskell.org/index.php?title=Library_submissions&diff=41433Library submissions2011-08-04T20:20:38Z<p>Simonpj: /* The Core Libraries */</p>
<hr />
<div>This page describes the process for maintaining the <br />
'''Core libraries'''. The core libraries are a subset of the packages in the<br />
Haskell Platform, and define basic APIs that are expected to be<br />
available in any Haskell implementation. They are listed under "The Core Libraries" below.<br />
<br />
Non-core libraries are, of course, managed by their own authors/maintainers (named in their .cabal file), using whatever policies those maintainers see fit. [Note: arguably the policies below might usefully be applied to all libraries embodied in the Haskell Platform, but that is a question for the HP team.]<br />
<br />
= General principles =<br />
<br />
* Each core package has a named maintainer, or small group of maintainers, who have commit access to the package. <br />
<br />
* Third parties are encouraged to make proposals for changes, both to the library API and its implementation, by sending the proposal to the maintainer (CC'ing the libraries mailing list).<br />
<br />
* The maintainer is trusted to decide what changes to make to the package, and when. They are strongly encouraged to follow the guidance below, but the general principle is: the community offers opinions, but the maintainers decide.<br />
<br />
<br />
= Responsiveness =<br />
<br />
* Third parties submitting proposals to the maintainer of a library can expect a timely and thoughtful response. <br />
* The more effort the proposer invests (for example, by constructing a patch rather than making an off-the-cuff suggestion) the more consideration s/he can reasonably expect.<br />
* Proposals that have widespread support, and are accompanied by patches (preferably with tests and documentation), should normally be accepted by the maintainer. <br />
* It is up to the maintainer to decide what "widespread" means; in particular, it does not always mean "a majority of those who responded". The majority-responder story is vulnerable to selection bias; e.g. 7 people (out of a client base of hundreds) say "add this function" but the maintainer thinks it will make the interface incrementally more complicated without sufficient benefit.<br />
* Where there is significant work involved in implementing a proposal, it is reasonable for a maintainer to ask for a patch. The principle is that maintainers are not obliged to do the work of implementing a proposal, even if it does enjoy wide support. For more substantial changes, it makes sense to develop the implementation in dialogue with the maintainer.<br />
<br />
= Guidance for proposers =<br />
<br />
A "proposal" can be anything from a one-sentence suggestion to a fully-implemented, tested, and documented patch.<br />
However, the more substantial the proposal the more attention you can expect. The process is this:<br />
<br />
* Send your proposal by email to the maintainer, with a copy to the libraries@haskell.org mailing list (which you need to [http://www.haskell.org/mailman/listinfo/libraries subscribe] to before posting).<br />
<br />
* Set a deadline for discussion (no less than two weeks), and act as chair/moderator for the discussion. <br />
<br />
* At the end of the discussion period, summarise your understanding of the consensus (or lack thereof), including a link to the thread in the mailing list archives, and send the summary to the maintainer for decision. The deadline gives you a moment to summarise the debate and hand over to the maintainer. It isn't a deadline for the maintainer to decide; for example he or she may seek more discussion first. <br />
<br />
* If the decision is positive, [http://hackage.haskell.org/trac/ghc/newticket create a ticket] on the GHC trac. The description of the ticket can summarise the proposal and link to the mail thread. Further discussion and implementation patches can be attached to the ticket, and the ticket helps the maintainer to keep track of what is on the go. (Obviously if the maintainer prefers some other mechanism, follow his or her guidance.)<br />
<br />
* For non-trivial changes the maintainer may ask for a patch. You may create the patch up front, and make it part of your proposal; or you may want to have some discussion about the design first, and only then roll up your sleeves to do the implementation; and for bigger jobs you may want to wait until the maintainer agrees in principle with the change.<br />
<br />
Here are desirable properties for a proposal and its implementation. The more of these properties your proposal or patch has, the more likely it is that the maintainer will adopt your idea. After all, to adopt it the maintainter will have to do whatever tasks you didn't do.<br />
<br />
* '''Description'''. A good proposal says clearly ''what'' you propose, ''why'' it is a good idea, and what its consequences would be.<br />
* '''Patch'''. Use <tt>darcs record</tt> or <tt>git commit</tt> (depending on what sort of repo the library lives in) to create it. Save the patch to a file, using <tt>darcs send --output</tt> or <tt>git format-patch</tt>. Make your changes against a copy of the master branch of the relevant library, and make sure it compiles.<br />
* '''Portability'''. Good code is portable. In particular, try to ensure the code runs in Hugs and GHC, and on Windows and Linux.<br />
* '''Style'''. Good code follows the conventions in the library you are modifying.<br />
* '''Documentation'''. Good code includes valid [http://haskell.org/haddock Haddock] documentation.<br />
* '''Tests'''. Good patches have suitable tests for the library's testsuite.<br />
<br />
= Guidance for maintainers =<br />
<br />
The principle is that we '''trust the maintainer''' to behave sensibly. The guidelines below are just that: guidelines, not rules. Still, the core libraries are used by many, many people, so maintainers should make every effort not to mess them up by accident. <br />
<br />
* '''API changes should be discussed''' on the libraries mailing list prior to making the change, even if the maintainer is the proposer. The maintainer still has ultimate say in what changes are made, but the community should have the opportunity to comment on changes. However, unanimity (or even a majority) is not required.<br />
<br />
* '''Every API change should be described precisely in the commit log.''' The commit logs should be sent to a public mailing list, or otherwise made easily available (e.g. via github), so that the community can keep an eye on changes and comment.<br />
<br />
* '''Backwards compatibility''' is important to many users. API changes are expected to retain backwards compatibility wherever possible. However, from time to time we may decide to have major revisions which are explicitly not backwards compatible; in these cases we may try to make the previous version of the package available concurrently, as in the base-3/base-4 switchover.<br />
<br />
* You don't need to consult the community for '''purely internal changes'''; i.e. changes that do not affect the library's clients.<br />
<br />
* Changes that simply '''widen the API by adding new functions''' are a bit of a grey area. It's better to consult the community, because there may be useful feedback about (say) the order of arguments, or the name of the function, or whatnot. On the other hand few clients will actually break if you add a new function to the API. Use your judgment.<br />
<br />
Libraries maintained by the GHC team are subject to the GHC validation policy - patches will be tested for validation before committing. Those packages not maintained by the GHC team will probably have a GHC lagging mirror repository that is subject to validation.<br />
<br />
= The Core Libraries =<br />
<br />
The following packages constitute the core libraries:<br />
<br />
{| border="1"<br />
! Package !! Maintainer<br />
|-<br />
| [http://hackage.haskell.org/package/array array] || GHC HQ<br />
|-<br />
| [http://hackage.haskell.org/package/base base] || GHC HQ<br />
|-<br />
| [http://hackage.haskell.org/package/containers containers] || Johan Tibell and Milan Straka<br />
|-<br />
| [http://hackage.haskell.org/package/directory directory] || GHC HQ<br />
|-<br />
| [http://hackage.haskell.org/package/mtl mtl] || Edward Kmett<br />
|-<br />
| [http://hackage.haskell.org/package/pretty pretty] || David Terei<br />
|-<br />
| [http://hackage.haskell.org/package/process process] || GHC HQ <br />
|-<br />
| [http://hackage.haskell.org/package/random random] || Ryan Newton<br />
|-<br />
| [http://hackage.haskell.org/package/unix unix] || GHC HQ<br />
|-<br />
|-<br />
| [http://hackage.haskell.org/package/template-haskell template-haskell] || GHC HQ<br />
|-<br />
| [http://hackage.haskell.org/package/parallel parallel] || Simon Marlow<br />
|-<br />
| [http://hackage.haskell.org/package/hpc hpc] || Andy Gill <br />
|-<br />
| [http://hackage.haskell.org/package/ghc-prim ghc-prim] || GHC HQ <br />
|-<br />
| [http://hackage.haskell.org/package/extensible-exceptions extensible-exceptions] || GHC HQ <br />
|-<br />
| [http://hackage.haskell.org/package/deepseq deepseq] || Simon Marlow<br />
|-<br />
| [http://hackage.haskell.org/package/Win32 Win32] || Bryan O'Sullivan<br />
|-<br />
| [http://hackage.haskell.org/package/xhtml xhtml] || Chris Dornan<br />
|}<br />
<br />
* The maintainer "GHC HQ" means Simon Marlow, Simon Peyton Jones, and Ian Lynagh. Daniel Fischer has taken responsibility for numeric stuff. Email cvs-ghc@haskell.org<br />
* "Volunteer needed" means that GHC HQ is the default maintainer, but that we'd like someone else to volunteer please!<br />
<br />
The following packages match the appropriate language standard, and as such cannot change independently. The code is maintained by the GHC team.<br />
<br />
{| border="1"<br />
|-<br />
| [http://hackage.haskell.org/package/haskell2010 haskell2010] || GHC HQ<br />
|-<br />
| [http://hackage.haskell.org/package/haskell98 haskell98] || GHC HQ<br />
|}<br />
<br />
These packages are maintained only for backward compatibility, and are not expected to undergo API changes in the future. <br />
<br />
{| border="1"<br />
|-<br />
| [http://hackage.haskell.org/package/old-locale old-locale] || GHC HQ <br />
|-<br />
| [http://hackage.haskell.org/package/old-time old-time] || GHC HQ <br />
|}<br />
<br />
= See also =<br />
<br />
* [http://hackage.haskell.org/trac/ghc/wiki/WorkingConventions GHC Working Conventions], including guidelines for submitting patches via darcs.<br />
* [http://haskell.org/haskellwiki/Category:Style Notes on programming style]<br />
<br />
[[Category:Community]]<br />
[[Category:Proposals| ]]</div>Simonpjhttps://wiki.haskell.org/index.php?title=Library_submissions&diff=41361Library submissions2011-07-29T15:28:02Z<p>Simonpj: /* The Core Libraries */</p>
<hr />
<div>This page describes the process for maintaining the <br />
'''Core libraries'''. The core libraries are a subset of the packages in the<br />
Haskell Platform, and define basic APIs that are expected to be<br />
available in any Haskell implementation. They are listed under "The Core Libraries" below.<br />
<br />
Non-core libraries are, of course, managed by their own authors/maintainers (named in their .cabal file), using whatever policies those maintainers see fit. [Note: arguably the policies below might usefully be applied to all libraries embodied in the Haskell Platform, but that is a question for the HP team.]<br />
<br />
= General principles =<br />
<br />
* Each core package has a named maintainer, or small group of maintainers, who have commit access to the package. <br />
<br />
* Third parties are encouraged to make proposals for changes, both to the library API and its implementation, by sending the proposal to the maintainer (CC'ing the libraries mailing list).<br />
<br />
* The maintainer is trusted to decide what changes to make to the package, and when. They are strongly encouraged to follow the guidance below, but the general principle is: the community offers opinions, but the maintainers decide.<br />
<br />
<br />
= Responsiveness =<br />
<br />
* Third parties submitting proposals to the maintainer of a library can expect a timely and thoughtful response. <br />
* The more effort the proposer invests (for example, by constructing a patch rather than making an off-the-cuff suggestion) the more consideration s/he can reasonably expect.<br />
* Proposals that have widespread support, and are accompanied by patches (preferably with tests and documentation), should normally be accepted by the maintainer. <br />
* It is up to the maintainer to decide what "widespread" means; in particular, it does not always mean "a majority of those who responded". The majority-responder story is vulnerable to selection bias; e.g. 7 people (out of a client base of hundreds) say "add this function" but the maintainer thinks it will make the interface incrementally more complicated without sufficient benefit.<br />
* Where there is significant work involved in implementing a proposal, it is reasonable for a maintainer to ask for a patch. The principle is that maintainers are not obliged to do the work of implementing a proposal, even if it does enjoy wide support. For more substantial changes, it makes sense to develop the implementation in dialogue with the maintainer.<br />
<br />
= Guidance for proposers =<br />
<br />
A "proposal" can be anything from a one-sentence suggestion to a fully-implemented, tested, and documented patch.<br />
However, the more substantial the proposal the more attention you can expect. The process is this:<br />
<br />
* Send your proposal by email to the maintainer, with a copy to the libraries@haskell.org mailing list (which you need to [http://www.haskell.org/mailman/listinfo/libraries subscribe] to before posting).<br />
<br />
* Set a deadline for discussion (no less than two weeks), and act as chair/moderator for the discussion. <br />
<br />
* At the end of the discussion period, summarise your understanding of the consensus (or lack thereof), including a link to the thread in the mailing list archives, and send the summary to the maintainer for decision. The deadline gives you a moment to summarise the debate and hand over to the maintainer. It isn't a deadline for the maintainer to decide; for example he or she may seek more discussion first. <br />
<br />
* If the decision is positive, [http://hackage.haskell.org/trac/ghc/newticket create a ticket] on the GHC trac. The description of the ticket can summarise the proposal and link to the mail thread. Further discussion and implementation patches can be attached to the ticket, and the ticket helps the maintainer to keep track of what is on the go. (Obviously if the maintainer prefers some other mechanism, follow his or her guidance.)<br />
<br />
* For non-trivial changes the maintainer may ask for a patch. You may create the patch up front, and make it part of your proposal; or you may want to have some discussion about the design first, and only then roll up your sleeves to do the implementation; and for bigger jobs you may want to wait until the maintainer agrees in principle with the change.<br />
<br />
Here are desirable properties for a proposal and its implementation. The more of these properties your proposal or patch has, the more likely it is that the maintainer will adopt your idea. After all, to adopt it the maintainter will have to do whatever tasks you didn't do.<br />
<br />
* '''Description'''. A good proposal says clearly ''what'' you propose, ''why'' it is a good idea, and what its consequences would be.<br />
* '''Patch'''. Use <tt>darcs record</tt> or <tt>git commit</tt> (depending on what sort of repo the library lives in) to create it. Save the patch to a file, using <tt>darcs send --output</tt> or <tt>git format-patch</tt>. Make your changes against a copy of the master branch of the relevant library, and make sure it compiles.<br />
* '''Portability'''. Good code is portable. In particular, try to ensure the code runs in Hugs and GHC, and on Windows and Linux.<br />
* '''Style'''. Good code follows the conventions in the library you are modifying.<br />
* '''Documentation'''. Good code includes valid [http://haskell.org/haddock Haddock] documentation.<br />
* '''Tests'''. Good patches have suitable tests for the library's testsuite.<br />
<br />
= Guidance for maintainers =<br />
<br />
The principle is that we '''trust the maintainer''' to behave sensibly. The guidelines below are just that: guidelines, not rules. Still, the core libraries are used by many, many people, so maintainers should make every effort not to mess them up by accident. <br />
<br />
* '''API changes should be discussed''' on the libraries mailing list prior to making the change, even if the maintainer is the proposer. The maintainer still has ultimate say in what changes are made, but the community should have the opportunity to comment on changes. However, unanimity (or even a majority) is not required.<br />
<br />
* '''Every API change should be described precisely in the commit log.''' The commit logs should be sent to a public mailing list, or otherwise made easily available (e.g. via github), so that the community can keep an eye on changes and comment.<br />
<br />
* '''Backwards compatibility''' is important to many users. API changes are expected to retain backwards compatibility wherever possible. However, from time to time we may decide to have major revisions which are explicitly not backwards compatible; in these cases we may try to make the previous version of the package available concurrently, as in the base-3/base-4 switchover.<br />
<br />
* You don't need to consult the community for '''purely internal changes'''; i.e. changes that do not affect the library's clients.<br />
<br />
* Changes that simply '''widen the API by adding new functions''' are a bit of a grey area. It's better to consult the community, because there may be useful feedback about (say) the order of arguments, or the name of the function, or whatnot. On the other hand few clients will actually break if you add a new function to the API. Use your judgment.<br />
<br />
Libraries maintained by the GHC team are subject to the GHC validation policy - patches will be tested for validation before committing. Those packages not maintained by the GHC team will probably have a GHC lagging mirror repository that is subject to validation.<br />
<br />
= The Core Libraries =<br />
<br />
The following packages constitute the core libraries:<br />
<br />
{| border="1"<br />
! Package !! Maintainer<br />
|-<br />
| [http://hackage.haskell.org/package/array array] || GHC HQ<br />
|-<br />
| [http://hackage.haskell.org/package/base base] || GHC HQ<br />
|-<br />
| [http://hackage.haskell.org/package/containers containers] || Johan Tibell and Milan Straka<br />
|-<br />
| [http://hackage.haskell.org/package/directory directory] || GHC HQ<br />
|-<br />
| [http://hackage.haskell.org/package/mtl mtl] || Edward Kmett<br />
|-<br />
| [http://hackage.haskell.org/package/pretty pretty] || David Terei<br />
|-<br />
| [http://hackage.haskell.org/package/process process] || GHC HQ <br />
|-<br />
| [http://hackage.haskell.org/package/random random] || Ryan Newton<br />
|-<br />
| [http://hackage.haskell.org/package/unix unix] || GHC HQ<br />
|-<br />
|-<br />
| [http://hackage.haskell.org/package/template-haskell template-haskell] || GHC HQ<br />
|-<br />
| [http://hackage.haskell.org/package/parallel parallel] || Simon Marlow<br />
|-<br />
| [http://hackage.haskell.org/package/hpc hpc] || Andy Gill <br />
|-<br />
| [http://hackage.haskell.org/package/ghc-prim ghc-prim] || GHC HQ <br />
|-<br />
| [http://hackage.haskell.org/package/extensible-exceptions extensible-exceptions] || GHC HQ <br />
|-<br />
| [http://hackage.haskell.org/package/deepseq deepseq] || Simon Marlow<br />
|-<br />
| [http://hackage.haskell.org/package/Win32 Win32] || Volunteer needed <br />
|-<br />
| [http://hackage.haskell.org/package/xhtml xhtml] || Volunteer needed <br />
|}<br />
<br />
* The maintainer "GHC HQ" means Simon Marlow, Simon Peyton Jones, and Ian Lynagh. Daniel Fischer has taken responsibility for numeric stuff. Email cvs-ghc@haskell.org<br />
* "Volunteer needed" means that GHC HQ is the default maintainer, but that we'd like someone else to volunteer please!<br />
<br />
The following packages match the appropriate language standard, and as such cannot change independently. The code is maintained by the GHC team.<br />
<br />
{| border="1"<br />
|-<br />
| [http://hackage.haskell.org/package/haskell2010 haskell2010] || GHC HQ<br />
|-<br />
| [http://hackage.haskell.org/package/haskell98 haskell98] || GHC HQ<br />
|}<br />
<br />
These packages are maintained only for backward compatibility, and are not expected to undergo API changes in the future. <br />
<br />
{| border="1"<br />
|-<br />
| [http://hackage.haskell.org/package/old-locale old-locale] || GHC HQ <br />
|-<br />
| [http://hackage.haskell.org/package/old-time old-time] || GHC HQ <br />
|}<br />
<br />
= See also =<br />
<br />
* [http://hackage.haskell.org/trac/ghc/wiki/WorkingConventions GHC Working Conventions], including guidelines for submitting patches via darcs.<br />
* [http://haskell.org/haskellwiki/Category:Style Notes on programming style]<br />
<br />
[[Category:Community]]<br />
[[Category:Proposals| ]]</div>Simonpjhttps://wiki.haskell.org/index.php?title=GHC/Using_the_FFI&diff=40995GHC/Using the FFI2011-07-14T07:29:03Z<p>Simonpj: /* Introduction */</p>
<hr />
<div>[[Category:GHC|FFI]]<br />
==Introduction==<br />
<br />
The examples below show how to call C++ functions in a Microsoft Windows Visual Studio DLL from Haskell, and Haskell functions from the C++ DLL. This illustrates that it is possible to link Haskell built with GHC to code produced by a different C compiler (GHC uses GCC), and also illustrates some workarounds to the specific problems encountered when building a standalone library (in this case a Windows DLL) that is to be called from Haskell.<br />
<br />
The examples are also relevant for the simpler case where you just want to statically link against C that is compiled with GCC. However, there are other pages that cover other aspects of Haskell's FFI:<br />
<br />
* [[FFI_Introduction|An introduction the Haskell FFI]]<br />
* [[FFI_complete_examples|Some complete examples of using the Haskell FFI]]<br />
* [[Using_Haskell_in_an_Xcode_Cocoa_project|Building a Haskell library to be used in a Mac OS X Cocoa project]]<br />
* [[FFICookBook|The FFI cookbook]]<br />
* [http://book.realworldhaskell.org/read/interfacing-with-c-the-ffi.html Interfacing with C: the FFI], Chapter 17 of [http://book.realworldhaskell.org Real World Haskell] by Bryan O'Sullivan, Don Stewart, and John Goerzen. It will guide you through the writing of the bindings to the PCRE library. Very useful and nicely conceived.<br />
<br />
* [http://www.cse.unsw.edu.au/~chak/haskell/ffi Foreign Function Interface] addendum to Haskell98 report<br />
* [http://research.microsoft.com/~simonpj/papers/marktoberdorf/ Tackling the Awkward Squad] A paper by Simon Peyton-Jones which includes discussion of the issues surrounding the design of the FFI<br />
<br />
== Importing C functions that turn out to be CPP macros ==<br />
<br />
Some C functions are actually defined by a CPP header file to be a C macro. Suppose you <tt>foreign import</tt> such a "function", thus:<br />
<haskell><br />
foreign import foo :: Int -> IO Int<br />
</haskell> <br />
Then you'll get the right thing if you compile using <tt>-fvia-C</tt>, provided you cause the right header files to be included. But the native code generator knows nothing of CPP mcros, so it will generate a call to a non-existent C function "foo".<br />
In effect, the FFI is defined to interface to the C ABI rather than the C API; it doesn't take account of CPP magic.<br />
<br />
To work around this you typically need to write yourself a C wrapper function (in C), thus:<br />
<haskell><br />
int foo_wrap(int x) { return foo(x); }<br />
</haskell><br />
This C wrapper lives in a .c file and gets compiled by the C compiler. Then use the Haskell FFI to foreign-import that, rather than calling the C function directly:<br />
<haskell><br />
foreign import "foo_wrap" foo :: Int -> IO Int<br />
</haskell> <br />
We have lots of examples scattered about the libraries already.<br />
<br />
==Callbacks into Haskell from foreign code==<br />
<br />
Suppose we have foreign code that takes a function as an argument:<br />
<br />
<tt>callerback.h</tt>:<br />
<br />
#ifndef CALLERBACK_H<br />
#define CALLERBACK_H<br />
typedef double (d2d)(double);<br />
double twice(d2d f, double x);<br />
#endif<br />
<br />
<tt>callerback.c</tt>:<br />
<br />
#include "callerback.h"<br />
double twice(d2d f, double x) {<br />
return f(f(x));<br />
}<br />
<br />
We can provide a Haskell function as an argument like this:<br />
<br />
<tt>CallBacker.hs</tt>:<br />
<br />
module Main(main) where<br />
<br />
-- we need CDouble for C's double type; Haskell's Double may be different<br />
import Foreign.C.Types(CDouble)<br />
-- we need function pointer type and free function<br />
import Foreign.Ptr(FunPtr, freeHaskellFunPtr)<br />
<br />
-- a "wrapper" import gives a factory for converting a Haskell function to a foreign function pointer<br />
foreign import ccall "wrapper"<br />
wrap :: (CDouble -> CDouble) -> IO (FunPtr (CDouble -> CDouble))<br />
<br />
-- import the foreign function as normal<br />
foreign import ccall "callerback.h twice"<br />
twice :: FunPtr (CDouble -> CDouble) -> CDouble -> IO CDouble<br />
<br />
-- here's the function to use as a callback<br />
square :: CDouble -> CDouble<br />
square x = x * x<br />
<br />
main :: IO ()<br />
main = do<br />
squareW <- wrap square -- make function pointer from the function<br />
let x = 4<br />
y <- twice squareW x -- use the foreign function with our callback<br />
z <- twice squareW y<br />
print y -- see that it worked<br />
print z<br />
freeHaskellFunPtr squareW -- clean up after ourselves<br />
<br />
This can be compiled and linked with this <tt>Makefile</tt>:<br />
<br />
CallBacker: CallBacker.hs callerback.c callerback.h<br />
ghc -O2 -Wall -fffi -o CallBacker CallBacker.hs callerback.c<br />
<br />
A very simple example, but hopefully enough to see what is going on.<br />
<br />
<br />
==Including the FFI header==<br />
The typedefs needed by foreign C functions are in <code>HsFFI.h</code>. However, this file includes various other files, which in turn include other files, and makes use of various definitions which would need to be defined somewhere etc, and doesn't compile under Visual C++ (for example).<br />
<br />
All in all, the simplest solution is to just make your own header with just the typedefs that are actually needed, and put this in your project directory, for example as <code>FFI.h</code>:<br />
#ifndef FFI_H<br />
#define FFI_H<br />
<br />
typedef unsigned int HsChar; // on 32 bit machine<br />
typedef int HsInt;<br />
typedef unsigned int HsWord;<br />
<br />
// Ensure that we use C linkage for HsFunPtr <br />
#ifdef __cplusplus<br />
extern "C"{<br />
#endif<br />
<br />
typedef void (*HsFunPtr)(void);<br />
<br />
#ifdef __cplusplus<br />
}<br />
#endif<br />
<br />
typedef void *HsPtr;<br />
typedef void *HsForeignPtr;<br />
typedef void *HsStablePtr;<br />
<br />
#define HS_BOOL_FALSE 0<br />
#define HS_BOOL_TRUE 1<br />
#endif // FFI_H<br />
<br />
Note that there is no point including prototypes for the functions <code>hs_free_fun_ptr</code> etc, because there is no way to link a standalone C library (such as a DLL) to them. However this is not a problem because your Haskell code can explicitly pass the Haskell versions of these functions (wrapped in a <code>FunPtr</code>) to your C library if you need them.<br />
<br />
<br />
<br />
==Calling Haskell from C==<br />
As mentioned above, when building a standalone C library, we can't link our C code to the C functions like <code>hs_free_fun_ptr</code>. However we can solve this problem by passing a <code>FunPtr</code> to the Haskell function <code>freeHaskellFunPtr</code> to our library at runtime.<br />
<br />
In the following code, we provide a Haskell function to try to initialize our C library (eg the DLL), run some Haskell code which would set up some call backs, enter some kind of message loop (eg for a Windows app), then deinitialize the C library:<br />
module Duma<br />
( run<br />
, module Duma.Font<br />
) where<br />
<br />
import Foreign.Ptr<br />
import Foreign.ForeignPtr<br />
import Control.Exception (bracket)<br />
import Duma.Font<br />
import Control.Monad (when)<br />
<br />
foreign import ccall duma_begin :: FunPtr (FunPtr a -> IO ()) -> IO Bool<br />
foreign import ccall duma_end :: IO ()<br />
foreign import ccall duma_run :: IO () -- implements a Windows message loop<br />
<br />
foreign import ccall "wrapper" mkFreeFunPtr :: (FunPtr a -> IO ()) -> IO (FunPtr (FunPtr a -> IO ()))<br />
<br />
run :: IO a -> IO ()<br />
run f = bracket<br />
(mkFreeFunPtr freeHaskellFunPtr<br />
)<br />
(\freeFunPtrFn -> do<br />
duma_end<br />
freeHaskellFunPtr freeFunPtrFn<br />
)<br />
(\freeFunPtrFn -> do<br />
initialized <- duma_begin freeFunPtrFn<br />
when (initialized)<br />
(f >> duma_run)<br />
)<br />
<br />
An example of C code would be:<br />
<br />
typedef void (*FunPtrFn)(HsFunPtr fn);<br />
FunPtrFn freeFunPtrFn = NULL;<br />
<br />
__declspec(dllexport) HsBool duma_begin(HsFunPtr freeFunPtrFnRaw){<br />
freeFunPtrFn = reinterpret_cast&lt;FunPtrFn&gt;(freeFunPtrFnRaw);<br />
return HS_BOOL_TRUE;<br />
}<br />
<br />
Then within some C function which needs to release a FunPtr, you can just write:<br />
(*freeFunPtrFn)(the_fun_ptr_to_free);<br />
<br />
Note that it is not safe to use the <code>freeFunPtrFn</code> to free itself, because some implementations of <code>FunPtr</code> store exit code (as well as entry code) in the <code>FunPtr</code> thus a <code>FunPtr</code> needs to be thought of as a function ''holder'' rather than just a function pointer (this is why the definition of <code>run</code> above frees the pointer from the Haskell side once we've already deinitialized the C library).<br />
<br />
A scavenger pattern ([http://www.haskell.org//pipermail/glasgow-haskell-users/2006-March/009907.html]) can be used to avoid the danger of a <code>FunPtr</code> being freed while the function it points to (actually ''holds'') is still being executed.<br />
<br />
Note that a direct pointer to the <code>hs_free_fun_ptr</code> function can be obtained this way:<br />
<br />
foreign import ccall "&" hs_free_fun_ptr :: FunPtr (FunPtr a -> IO ())<br />
<br />
==Improving efficiency==<br />
There are two types of foreign call:<br />
# those where the foreign function may call back into Haskell (includes anything which makes use of the Haskell runtime) before the original foreign call returns<br />
# those where the function will always return without first calling back into Haskell.<br />
In the first case, a significant amount of book-keeping is required to ensure that Haskell is ready to accept "incomming" calls from the foreign function before it returns, whereas in the second, since there is no danger of a call back into the Haskell runtime, nothing special needs to be done except to marshal the arguments and result as usual. Therefore the second type of call can be made a lot faster.<br />
To specify which type of call to use with a given foreign function, the FFI provides the keywords <code>safe</code> and <code>unsafe</code>. The default is <code>safe</code> (calls which might call back into Haskell before returning), so we only need to annotate those functions which we know will not call back into Haskell eg in our example above:<br />
<br />
foreign import ccall unsafe duma_createFont :: CString -> IO (Ptr RawFont)<br />
foreign import ccall unsafe<br />
"&duma_releaseFont" -- note the ampersand<br />
duma_releaseFont :: FunPtr (Ptr RawFont -> IO ())<br />
<br />
Note that <code>duma_run</code> still needs to be <code>safe</code> because it will execute Haskell IO actions in response to Windows messages (the actual code for doing this is not included in the example), and <code>duma_end</code> also needs to be <code>safe</code> because it will make use of the Haskell function <code>freeHaskellFunPtr</code> (or <code>hs_free_fun_ptr</code>) to free any callbacks that were registered before returning. The annotation you choose for <code>duma_begin</code> would depend on whether or not you need to call back into the Haskell runtime during initialization of your DLL.<br />
<br />
Caution! If you are not responsible for the source of the foreign function you should not mark the import as <code>unsafe</code> unless you are absolutely certain it doesn't (and won't ever) call back into Haskell... If in doubt, consider posting a question to the Haskell Cafe or GHC User's mailing list.<br />
<br />
==GHC and DLLs==<br />
<br />
===Example of aquiring and using a foreign resource===<br />
Suppose you are writing a DLL to provide a nice windowing environment for Haskell, and you want to let Haskell obtain a text font. Suppose a font is implemented by the C++ class Font, defined by:<br />
// Duma_Font.h<br />
namespace Duma {<br />
class Font {<br />
public:<br />
Font(const char *name) : refcount(0){/* details omitted! */}<br />
~Font(){}<br />
<br />
void AddRef() const{++refcount;}<br />
void Release() const{if (!--refcount) delete this;}<br />
<br />
private:<br />
mutable unsigned int refcount;<br />
};<br />
} // Duma<br />
<br />
Continuing with our example DLL called <code>Duma</code>, we now edit <code>Duma.h</code> to add the following prototypes:<br />
// Duma.h<br />
#ifndef __DUMA_H // be careful to use #ifndef (!)<br />
#define __DUMA_H<br />
<br />
// This header needs to be understood by VC++ and GCC<br />
// When included in the source for building the DLL,<br />
// __DUMA_DLL_EXPORT must be defined<br />
<br />
#ifdef __DUMA_DLL_EXPORT<br />
#define DUMA_API __declspec(dllexport)<br />
#else<br />
#define DUMA_API<br />
#endif<br />
<br />
#ifdef __cplusplus<br />
extern "C" {<br />
#endif<br />
<br />
DUMA_API HsPtr duma_createFont(const char *name);<br />
DUMA_API void duma_releaseFont(HsPtr fontRaw);<br />
<br />
#ifdef __cplusplus<br />
}<br />
#endif<br />
#endif // __DUMA_H<br />
<br />
We need to tell GHC about these, so we edit <code>Duma.def</code>:<br />
LIBRARY Duma<br />
EXPORTS<br />
duma_createFont<br />
duma_releaseFont<br />
<br />
Then we implement them in <code>Duma.cpp</code>:<br />
// Duma.cpp<br />
#include "stdafx.h"<br />
#include "FFI.h"<br />
<br />
// Note we have to define __DUMA_DLL_EXPORT and also<br />
// make sure FFI.h is included before we inlcude Duma.h<br />
#define __DUMA_DLL_EXPORT<br />
#include "Duma.h"<br />
#include "Duma_Font.h"<br />
<br />
BOOL APIENTRY DllMain( HANDLE hModule, <br />
DWORD ul_reason_for_call, <br />
LPVOID lpReserved<br />
){<br />
// Note this is a *very* dangerous function so do nothing at all in here<br />
// It is not known which DLLs are currently loaded<br />
// If you need to do initialization/deinitialization, you should do<br />
// this explicitly by exporting init/deinit functions to be called from<br />
// Haskell<br />
return TRUE;<br />
}<br />
<br />
using namespace Duma;<br />
<br />
#ifdef __cplusplus<br />
extern "C" {<br />
#endif<br />
<br />
DUMA_API HsPtr duma_createFont(const char *name){<br />
Font *fontRaw = new Font(name);<br />
fontRaw->AddRef();<br />
return fontRaw;<br />
}<br />
<br />
DUMA_API void duma_releaseFont(HsPtr fontRaw){<br />
reinterpret_cast&lt;Font *&gt;(fontRaw)->Release();<br />
}<br />
<br />
#ifdef __cplusplus<br />
}<br />
#endif<br />
<br />
The header <code>Duma.h</code> is used both within our DLL and externally, by GCC, to verify that the foreign function prototypes match those expected by the FFI. When used within the DLL, we make <code>DUMA_API</code> expand to the relevant linkage declaration for Visual C++ by defining <code>__DUMA_DLL_EXPORT</code>. Since (we hope) this symbol will not be defined when GCC sees the header, GCC will see a view of the header suitable for it.<br />
<br />
Also in regards to the header, we have made our own local FFI typedefs to avoid the problems of trying to get <code>HsFFI.h</code> and all that it includes, to compile. However GCC will see the real <code>HsFFI.h</code> so when we include <code>Duma.h</code> in our DLL, we have to remember to include <code>FFI.h</code> before it. Of course we could have used some other symbol and another <code>#ifdef</code> in <code>Duma.h</code> to cause <code>FFI.h</code> to be included when needed but since <code>Duma.h</code> is only used in one place in the DLL ie by <code>Duma.cpp</code> there does not seem much point in going to this extra trouble.<br />
<br />
The next thing is to create a Haskell module which will allow us to treat fonts as values which are automatically released when they are no longer needed, so for this we edit a module eg <code>Duma.Font</code> by creating a directory called <code>Duma</code> in the same directory as your C++ files, then creating a file <code>Font.hs</code> in this directory:<br />
module Duma.Font<br />
( createFont<br />
, Font<br />
) where<br />
<br />
import Foreign.C.String<br />
import Foreign.Ptr<br />
import Foreign.ForeignPtr<br />
import Control.Exception (block)<br />
<br />
data RawFont -- corresponds to the C++ Font<br />
newtype Font = Font (ForeignPtr RawFont) deriving (Eq, Ord)<br />
<br />
foreign import ccall duma_createFont :: CString -> IO (Ptr RawFont)<br />
foreign import ccall<br />
"&duma_releaseFont" -- note the ampersand<br />
duma_releaseFont :: FunPtr (Ptr RawFont -> IO ())<br />
<br />
createFont :: String -> IO Font<br />
createFont name = block $ do<br />
f <- (withCString name $ \cname -> duma_createFont cname) >>=<br />
newForeignPtr duma_releaseFont<br />
return $ Font f<br />
<br />
There are several points to note about this code:<br />
# We are using three types of pointers:<br />
#; <code>Ptr</code> : Corresponds to a plain C pointer<br />
#; <code>FunPtr</code> : Points to a Haskell or (in this case) C function, and encapsulates marshalling details necessary both before entry and after leaving the function. ''For this reason a <code>FunPtr</code> must never be destroyed while the function it points to is still being executed''<br />
#; <code>ForeignPtr</code> : Associates a plain C pointer with a finalizer function which will be invoked when the ForeignPtr value is garbage collected<br />
# It is important to realise that the type declaration of a foreign import shows the type of the Haskell value, not the type of the corresponding C entity that the Haskell value is bound to. When the specification of the C entity in quotes is omitted, the FFI binds a Haskell value of type <code>A -> B</code> (or <code>IO B</code>) to a C function that takes a single argument of type <code>A</code> and returns a value of type <code>B</code>. If the Haskell value just has type <code>B</code> (or <code>IO B</code>), the FFI expects to find a C ''function'' that takes ''no arguments'' and returns a value of type <code>B</code>. However in the case of <code>duma_releaseFont</code>, the Haskell value is a function pointer, and we want this to ''point to'' the C function <code>duma_releaseFont</code>, thus we need to explicitly specify the C entity being bound and put an ampersand before the C name, to indicate that we are binding to the ''address'' of the C function not the C function itself. If we omitted the ampersand, the FFI would think that the C entity to use was a function taking no arguments that returned the function pointer rather than actually being the function pointer itself. It is worth taking the time to achieve clarity about the difference between a function and a pointer to a function, especially since this distinction is blurred in C by the implicit "casting" of a function name (which is considered to ''be'' the function itself, and which is not a first class value in C) to the address of a function. Luckily, if you are building with an optimized build, or use the <code>-fviaC</code> option, GCC will give an error message if you forget the ampersand, but beware: GHC native compilation will silently succeed and your app will mysteriously crash.<br />
# <code>block</code> is used to make the creation of the font atomic with respect to asynchronous exceptions<br />
# <code>withCString</code> marshalls a Haskell <code>String</code> to a null terminated C string, and <code>newForeignPtr</code> takes the <code>Ptr RawFont</code> returned by <code>duma_createFont</code> and returns a <code>ForeignPtr RawFont</code> so that <code>duma_releaseFont</code> will be called on the underlying <code>Ptr RawFont</code> when the <code>ForeignPtr RawFont</code> value is no longer needed. Finally we wrap the <code>ForeignPtr RawFont</code> in a newtype to hide all this from the end user.<br />
<br />
===Debugging Haskell DLLs===<br />
<br />
Some folks tend to use print, putStrLn, hPutStrLn and friends to emit debug messages to stdout or stderr. This works fine, if you are developing console application, but if you are writing DLL then you can't be sure that it will be embeded in a process with console interface. The problem is that when the process is with graphical interface, then it doesn't have associated stdin, stdout and stderr at all. Any attempt to use putStrLn for example will raise an exception and the process will terminate. The solution is to use Debug.Trace.trace or Debug.Trace.putTraceMsg instead. When they are called from a process with console interface then the messages are redirected to stderr. When the process is with graphical interface then the debugger console is used instead. If you want to debug your DLL, then launch the embedding process from your favorite debugger (gdb, WinDbg or Visual Studio for example) and you will see all debug messages in its output console.<br />
<br />
===Beware of DllMain()!===<br />
<br />
The body of a <tt>DllMain()</tt> function is an '''extremely''' dangerous place! This is because the order in which DLLs are unloaded when a process is terminating is unspecified. This means that the <tt>DllMain()</tt> for your DLL may be called when other DLLs containing functions that you call when de-initializing your DLL have already been unloaded. In other words, you can't put shutdown code inside DllMain(), unless your shutdown code only requires use of certain functions which are guaranteed to be available (see the Platform SDK docs for more info).<br />
<br />
In particular, if you are writing a DLL that's statically linked with Haskell, it is not safe to call <tt>hs_exit()</tt> from <tt>DllMain()</tt>, since <tt>hs_exit()</tt> may make use of other DLLs. (For example it causes finalizers to be run and a finalizer may need to make use of a function in some other DLL.)<br />
<br />
A solution is to always export <tt>Begin()</tt> and <tt>End()</tt> functions from your DLL, and call these from the application that uses the DLL, so that you can be sure that all DLLs needed by any shutdown code in your <tt>End()</tt> function are available when it is called.<br />
<br />
''The following example is untested but illustrates the idea. It would be good if someone could check over it or replace by a real life example.'' Suppose we have a DLL called '''Lewis''' which makes use of 2 Haskell modules '''Bar''' and '''Zap''', where '''Bar''' imports '''Zap''' and is therefore the ''root module'' in the sense of [http://www.haskell.org/ghc/docs/latest/html/users_guide/sec-ffi-ghc.html GHC user's manual section 8.2.1.1]. Then the main C++ unit for the DLL would look something like:<br />
<br />
// Lewis.cpp -- compiled using GCC<br />
#include <Windows.h><br />
#include "HsFFI.h"<br />
<br />
#define __LEWIS_DLL_EXPORT<br />
#include "Lewis.h"<br />
<br />
#include "Bar_stub.h" // generated by GHC<br />
#include "Zap_stub.h"<br />
<br />
BOOL APIENTRY DllMain( HANDLE hModule, <br />
DWORD ul_reason_for_call, <br />
LPVOID lpReserved<br />
){<br />
return TRUE;<br />
}<br />
<br />
extern "C"{<br />
<br />
LEWIS_API HsBool lewis_Begin(){<br />
int argc = ...<br />
char *argv[] = ...<br />
<br />
// Initialize Haskell runtime<br />
hs_init(&argc, &argv);<br />
<br />
// Tell Haskell about all root modules<br />
hs_add_root(__stginit_Bar);<br />
<br />
// do any other initialization here and<br />
// return false if there was a problem<br />
return HS_BOOL_TRUE;<br />
}<br />
<br />
LEWIS_API void lewis_End(){<br />
hs_exit();<br />
}<br />
<br />
LEWIS_API HsInt lewis_Test(HsInt x){<br />
// use Haskell functions exported by<br />
// modules Bar and/or Zap<br />
<br />
return ...<br />
}<br />
<br />
} // extern "C"<br />
<br />
and some application which used the functions in the DLL would have a <tt>main()</tt> function like:<br />
<br />
// MyApp.cpp<br />
#include "stdafx.h"<br />
#include "Lewis.h"<br />
<br />
int main(int argc, char *argv[]){<br />
if (lewis_Begin()){<br />
// can now safely call other functions<br />
// exported by Lewis DLL<br />
<br />
}<br />
lewis_End();<br />
return 0;<br />
}<br />
<br />
<tt>Lewis.h</tt> would have to have some appropriate <tt>#ifndef</tt> to ensure that the Haskell FFI types were defined for external users of the DLL (who wouldn't necessarily have GHC installed and therefore wouldn't have the include files like <tt>HsFFI.h</tt> etc).<br />
<br />
=== Setting up your build environment (Visual Studio Specific) ===<br />
* If you haven't already done so, create a new windows environment variable called <code>GHC_HOME</code> and set it to <code>c:\ghc\ghc-6.4.2</code> or wherever you've installed GHC<br />
* Create a directory eg <code>c:\dll</code> to store all your DLLs<br />
* Add this to the <code>PATH</code> environment variable so that Windows will find your DLL at runtime (Also your path should contain <code>%GHC_HOME%\bin;%GHC_HOME%\gcc-lib</code> if you also want to compile from the command line)<br />
* Create a new Visual Studio DLL project. For the purposes of this example, we will call this <code>Duma</code>.<br />
* In the Solution pane, right click on <code>Duma</code> then select Properties &rarr; Build Events &rarr; Post-Build Event and add the following event:<br />
Command Line: copy "$(TargetDir)Duma.dll" c:\dll<br />
Description: Copying duma.dll<br />
Excluded From Build: No<br />
* In the Solution Pane, rename the folder <code>Source Files</code> to <code>Code Files</code> and adjust the properties of this folder so that <code>.h</code> files are also filtered into it. (This is a good idea for any C++ project because it keeps the <code>.cpp</code> and <code>.h</code> together in the same list which makes editing a C++ unit a lot easier.)<br />
* Also rename the folder <code>Header Files</code> to <code>Haskell Files</code> and change its filter to select <code>.hs</code> files.<br />
* In the <code>Code Files</code> folder, create a text file called <code>Duma.def</code>, then select Properties &rarr; Custom Build Step &rarr; General and enter the following:<br />
Command Line: %GHC_HOME%\gcc-lib\dlltool -d "$(InputDir)Duma.def" -l c:\dll\libDuma.a<br />
Description: Creating libDuma.a from .def<br />
Outputs: c:\dll\libDuma.a<br />
Additional Dependencies:<br />
This makes the functions you will export from your DLL visible to GHC and GCC. (The path to dlltool given above will need to be changed if you have installed GHC in a different place.)<br />
* Also in the <code>Code Files</code> folder, create a text file called <code>ghc.bat</code> with the following content:<br />
echo off<br />
REM Optimized build<br />
%GHC_HOME%\bin\ghc.exe -fglasgow-exts -fffi -I. -#include Duma.h --make main.hs -O2 -optl-lDuma -optl-L"c:\dll"<br />
if errorlevel 1 goto failed<br />
echo Success :-)<br />
goto end<br />
:failed<br />
echo Failure :-(<br />
:end<br />
(The above batch file is based on that kindly supplied by Neil Mitchell on the GHC mailing list.)<br />
<br />
You may also want to use <code>-optl-mwindows</code> if you don't want Haskell to create a console window.<br />
* In Tools &rarr; External Tools, click <code>Add</code> and specify the following:<br />
Title: &ghc<br />
Command: ghc.bat<br />
Arguments:<br />
Initial directory: $(ProjectDir)<br />
Remember to tick the <code>Use Output Window</code> box so you can see what's happening on the output pane of Visual Studio.<br />
<br />
After you've done all this, you can build your DLL as usual by hitting <code>Control-Shift-B</code> and then make your Haskell program that uses the DLL by using <code>Alt-t-g</code> (assuming that your <code>main.hs</code> is in the same directory as the C files). When you just make changes to your DLL, you can use <code>F5</code> as normal (the first time you do this you will have to type <code>main.exe</code> into the box where it asks you for the main executable to use).<br />
<br />
If you later install a newer version of GHC, you only need to modify the GHC_HOME windows environment variable.<br />
<br />
== Using GHC for DLLs in Excel ==<br />
<br />
This part illustrates the preceding '''Beware of dllMain()!''' section of this document. It extends the information found in the [http://www.haskell.org/ghc/dist/current/docs/users_guide/win32-dlls.html Building and using Win32 DLLs] article. For build instructions and base code, refer to this article.<br />
<br />
=== Excel crash on Exit when using a GHC DLL ===<br />
<br />
Calling shutdownHaskell from the dllMain function, as in the given example can cause Excel to crash on exit.<br />
<br />
As explained in section '''Beware of DllMain()!''' of this article, it's safer to call startupHaskell and shutdownHaskell from outside DllMain.<br />
<br />
=== Updated dllMain.c code ===<br />
<br />
Here is an updated <code>dllMain.c</code> code with additional initialization and shutdown functions (tested).<br />
<br />
<pre><br />
#include <windows.h><br />
#include <Rts.h><br />
<br />
#define __ADDER_DLL_EXPORT<br />
#define ADDER_API _declspec(dllexport)<br />
<br />
extern void __stginit_Adder(void);<br />
<br />
static char* args[] = { "ghcDll", NULL };<br />
/* N.B. argv arrays must end with NULL */<br />
<br />
BOOL STDCALL DllMain( HANDLE hModule, <br />
DWORD ul_reason_for_call, <br />
LPVOID lpReserved<br />
){<br />
return TRUE;<br />
}<br />
<br />
ADDER_API BOOL adder_Begin(){<br />
startupHaskell(1, args, __stginit_Adder);<br />
return HS_BOOL_TRUE;<br />
}<br />
<br />
ADDER_API void adder_End(){<br />
shutdownHaskell();<br />
}<br />
</pre><br />
<br />
=== VBA code for Dll initialization and shutdown ===<br />
<br />
We must call <code>adder_Begin</code> before any call to the DLL exported functions and <code>adder_End</code> before the DLL is unload. Excel VBA provides us with two callback functions that seems appropriate for this: <code>Workbook_Open</code> and <code>Workbook_BeforeClose</code>.<br />
<br />
Function declaration in Excel is extended to add the two initalization and shutdown functions. I put it in a new module so I can make them public. The code looks like this:<br />
<br />
<pre><br />
Public Declare Function adder Lib "adder.dll" Alias "adder@8" (ByVal x As Long, ByVal y As Long) As Long<br />
Public Declare Function adder_Begin Lib "adder.dll" () As Boolean<br />
Public Declare Sub adder_End Lib "adder.dll" ()<br />
</pre><br />
<br />
The callback functions have to be defined in the <code>ThisWorkbook</code> module and look like this:<br />
<br />
<pre><br />
Private Sub Workbook_BeforeClose(Cancel As Boolean)<br />
adder_End<br />
End Sub<br />
<br />
Private Sub Workbook_Open()<br />
adder_Begin<br />
End Sub<br />
</pre><br />
<br />
=== Known problems ===<br />
<br />
If closing Excel is canceled the <code>Workbook_BeforeClose</code> function will be called and haskell will be shutdown leaving the Workbook open but with Haskell down. The application will crash on the next DLL function call. This is easy to reproduce, modify the WorkBook, close it without saving and press <code>Cancel</code>. Change some value to cause a GHC function to be called and Enjoy Excel crashing.<br />
<br />
==Random Questions==<br />
===Are FunPtr's stable?===<br />
Yes. Once you've obtained a FunPtr the FunPtr remains valid until it is explicitly freed (ie the garbage collector will not break it). See [http://research.microsoft.com/~simonpj/papers/marktoberdorf/ Tackling the Awkward Squad] section 6.4.2<br />
<br />
===Can I free a FunPtr from inside the function itself?===<br />
Yes (unless you are on IA64, right now). See [http://www.haskell.org//pipermail/glasgow-haskell-users/2006-March/009907.html this thread] (the later messages in particular) for more details.</div>Simonpjhttps://wiki.haskell.org/index.php?title=GHC/Type_families&diff=40688GHC/Type families2011-06-29T13:03:13Z<p>Simonpj: /* Injectivity, type inference, and ambiguity */</p>
<hr />
<div>Indexed type families, or '''type families''' for short, are a Haskell extension supporting ad-hoc overloading of data types. Type families are parametric types that can be assigned specialized representations based on the type parameters they are instantiated with. They are the data type analogue of [[Type class|type classes]]: families are used to define overloaded ''data'' in the same way that classes are used to define overloaded ''functions''. Type families are useful for generic programming, for creating highly parameterised library interfaces, and for creating interfaces with enhanced static information, much like dependent types.<br />
<br />
Type families come in two flavors: ''data families'' and ''type synonym families''. Data families are the indexed form of data and newtype definitions. Type synonym families are the indexed form of type synonyms. Each of these flavors can be defined in a standalone manner or ''associated'' with a type class. Standalone definitions are more general, while associated types can more clearly express how a type is used and lead to better error messages.<br />
<br />
''NB: see also Simon's [http://hackage.haskell.org/trac/ghc/blog/LetGeneralisationInGhc7 blog entry on let generalisation] for a significant change in the policy for let generalisation, driven by the type family extension. In brief: a few programs will puzzlingly fail to compile with <tt>-XTypeFamilies</tt> even though the code is legal Haskell 98.''<br />
<br />
== What are type families? ==<br />
<br />
The concept of a type family comes from type theory. An indexed type family in type theory is a partial function at the type level. Applying the function to parameters (called ''type indices'') yields a type. Type families permit a program to compute what data constructors it will operate on, rather than having them fixed statically (as with simple type systems) or treated as opaque unknowns (as with parametrically polymorphic types).<br />
<br />
Type families are to vanilla data types what type class methods are to regular functions. Vanilla polymorphic data types and functions have a single definition, which is used at all type instances. Classes and type families, on the other hand, have an interface definition and any number of instance definitions. A type family's interface definition declares its [[kind]] and its arity, or the number of type indices it takes. Instance definitions define the type family over some part of the domain.<br />
<br />
As a simple example of how type families differ from ordinary parametric data types, consider a strict list type. We can represent a list of <hask>Char</hask> in the usual way, with cons cells. We can do the same thing to represent a list of <hask>()</hask>, but since a strict <hask>()</hask> value carries no useful information, it would be more efficient to just store the length of the list. This can't be done with an ordinary parametric data type, because the data constructors used to represent the list would depend on the list's type parameter: if it's <hask>Char</hask> then the list consists of cons cells; if it's <hask>()</hask>, then the list consists of a single integer. We basically want to select between two different data types based on a type parameter. Using type families, this list type could be declared as follows:<br />
<br />
<haskell><br />
-- Declare a list-like data family<br />
data family XList a<br />
<br />
-- Declare a list-like instance for Char<br />
data instance XList Char = XCons !Char !(XList Char) | XNil<br />
<br />
-- Declare a number-like instance for ()<br />
data instance XList () = XListUnit !Int<br />
</haskell><br />
<br />
The right-hand sides of the two <code>data instance</code> declarations are exactly ordinary data definitions. However, they define two instances of the same parametric data type, <hask>XList Char</hask> and <hask>XList ()</hask>, whereas ordinary data declarations define completely unrelated types. A recent [[Simonpj/Talk:FunWithTypeFuns|tutorial paper]] has more in-depth examples of programming with type families. <br />
<br />
GADTs bear some similarity to type families, in the sense that they allow a parametric type's constructors to depend on the type's parameters. However, all GADT constructors must be defined in one place, whereas type families can be extended. Functional dependences are similar to type families, and many type classes that use functional dependences can be equivalently expressed with type families. Type families provide a more functional style of type-level programming than the relational style of functional dependences.<br />
<br />
== What do I need to use type families? ==<br />
<br />
Type families are a GHC extension enabled with the <code>-XTypeFamilies</code> flag or the <code>{-# LANGUAGE TypeFamilies #-}</code> pragma. The first stable release of GHC that properly supports type families is 6.10.1. (The 6.8 release included an early partial implementation, but its use is deprecated.) Please [http://hackage.haskell.org/trac/ghc/query?status=new&status=assigned&status=reopened&group=priority&type=bug&order=id&desc=1 report bugs] via the GHC bug tracker, ideally accompanied by a small example program that demonstrates the problem. Use the [mailto:glasgow-haskell-users@haskell.org GHC mailing list] for questions or for a discussion of this language extension and its description on this wiki page.<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-families.html#data-family-declarations ''kind signature''] (here <hask>* -> *</hask>) for the associated data type <hask>GMap k</hask> - analogous 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.IntMap</hask>, thusly:<br />
<haskell><br />
instance GMapKey Int where<br />
data GMap Int v = GMapInt (Data.IntMap.IntMap v)<br />
empty = GMapInt Data.IntMap.empty<br />
lookup k (GMapInt m) = Data.IntMap.lookup k m<br />
insert k v (GMapInt m) = GMapInt (Data.IntMap.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 fundamental 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 />
Next, 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 b) v (GMapEither gm1 gm2) = GMapEither gm1 (insert b v gm2)<br />
</haskell><br />
If you find this code algorithmically surprising, I'd suggest to have a look at [http://www.cs.ox.ac.uk/ralf.hinze/publications/index.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 querying 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 source code[http://darcs.haskell.org/testsuite/tests/ghc-regress/indexed-types/should_run/GMapAssoc.hs] for <hask>GMap</hask> from GHC's test suite.<br />
<br />
== Detailed definition of data families ==<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-indices to coincide with the class parameters. However, the latter 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> keyword. 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-indices. 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. In other words: '''the named type parameters of the data declaration must be a permutation of a subset of the class variables'''. <br />
<br />
Example is admissible:<br />
<haskell><br />
class C a b c where { data T c a :: * } -- OK<br />
class C a b c where { data T a a :: * } -- Bad: repeated variable<br />
class D a where { data T a x :: * } -- Bad: x is not a class variable<br />
class D a where { data T a :: * -> * } -- OK<br />
</haskell><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, but may not contain forall types or type synonym families. However, data families are generally allowed in type parameters, and type synonyms are allowed as long as they are fully applied and expand to a type that is itself admissible - exactly as this is required for occurrences of type synonyms in class instance parameters. 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 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 />
nonsense :: T a -> Int<br />
nonsense A = 1 -- WRONG: These two equations together...<br />
nonsense 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 - 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 indices corresponding to class parameters must be identical to the type given in the instance head; here this is the 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 instance 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 />
==== Scoping of class parameters ====<br />
<br />
In the case of multi-parameter type classes, the visibility of class parameters in the right-hand side of associated family instances depends ''solely'' on the parameters of the data family. As an example, consider the simple class declaration<br />
<haskell><br />
class C a b where<br />
data T a<br />
</haskell><br />
Only one of the two class parameters is a parameter to the data family. Hence, the following instance declaration is invalid:<br />
<haskell><br />
instance C [c] d where<br />
data T [c] = MkT (c, d) -- WRONG!! 'd' is not in scope<br />
</haskell><br />
Here, the right-hand side of the data instance mentions the type variable <hask>d</hask> that does not occur in its left-hand side. We cannot admit such data instances as they would compromise type safety.<br />
<br />
==== Type class instances of family 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 implicitly 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 is 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>GMapEither</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 />
== An associated type synonym example ==<br />
<br />
Type synonym families are an alternative to functional dependencies, which makes functional dependency examples well suited to introduce type synonym families. In fact, type families are a more functional way to express the same as functional dependencies (despite the name!), as they replace the relational notation of functional dependencies by an expression-oriented notation; i.e., functions on types are really represented by functions and not relations.<br />
<br />
=== The <hask>class</hask> declaration ===<br />
<br />
Here's an example from Mark Jones' seminal paper on functional dependencies:<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 />
Instead of the multi-parameter type class, we use a single parameter class, and the parameter <hask>e</hask><br />
turned into an associated type synonym <hask>Elem ce</hask>.<br />
<br />
=== An <hask>instance</hask>===<br />
<br />
Instances change correspondingly. An instance of the two-parameter class<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) <br />
| e == x = True<br />
| otherwise = member e xs<br />
toList l = l<br />
</haskell><br />
becomes an instance of a single-parameter class, where the dependent type parameter turns into an associated type instance declaration:<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) <br />
| 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 />
== Detailed definition of type synonym families ==<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-indices to coincide with the class parameters. However, the latter 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 />
Parameters can also be given explicit kind signatures if needed. We call the number of parameters in a type family declaration, the family's arity, and all applications of a type family must be fully saturated w.r.t. to that arity. This requirement is unlike ordinary type synonyms and it implies that the kind of a type family is not sufficient to determine a family's arity, and hence in general, also insufficient to determine whether a type family application is well formed. As an example, consider the following declaration:<br />
<haskell><br />
type family F a b :: * -> * -- F's arity is 2, <br />
-- although its overall kind is * -> * -> * -> *<br />
</haskell><br />
Given this declaration the following are examples of well-formed and malformed types:<br />
<haskell><br />
F Char [Int] -- OK! Kind: * -> *<br />
F Char [Int] Bool -- OK! Kind: *<br />
F IO Bool -- WRONG: kind mismatch in the first argument<br />
F Bool -- WRONG: unsaturated application<br />
</haskell><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 />
Exactly as in the case of an associated data declaration, '''the named type parameters must be a permutation of a subset of the class parameters'''. Examples<br />
<haskell><br />
class C a b c where { type T c a :: * } -- OK<br />
class D a where { type T a x :: * } -- No: x is not a class parameter<br />
class D a where { type T a :: * -> * } -- OK<br />
</haskell><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, but may not contain forall types or type synonym families. However, data families are generally allowed, and type synonyms are allowed as long as they are fully applied and expand to a type that is admissible - these are the exact same requirements as for data instances. For example, the <hask>[e]</hask> instance for <hask>Elem</hask> is<br />
<haskell><br />
type instance Elem [e] = e<br />
</haskell><br />
<br />
A type family instance declaration must satisfy the following rules:<br />
* An appropriate family declaration is in scope - just like class instances require the class declaration to be visible. <br />
* The instance declaration conforms to the kind determined by its family declaration<br />
* The number of type parameters in an instance declaration matches the number of type parameters in the family declaration.<br />
* The right-hand side of a type instance must be a monotype (i.e., it may not include foralls) and after the expansion of all saturated vanilla type synonyms, no synonyms, except family synonyms may remain.<br />
<br />
Here are some examples of admissible and illegal type instances:<br />
<haskell><br />
type family F a :: *<br />
type instance F [Int] = Int -- OK!<br />
type instance F String = Char -- OK!<br />
type instance F (F a) = a -- WRONG: type parameter mentions a type family<br />
type instance F (forall a. (a, b)) = b -- WRONG: a forall type appears in a type parameter<br />
type instance F Float = forall a.a -- WRONG: right-hand side may not be a forall type<br />
<br />
type family G a b :: * -> *<br />
type instance G Int = (,) -- WRONG: must be two type parameters<br />
type instance G Int Char Float = Double -- WRONG: must be two type parameters<br />
</haskell><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 instance 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 only overlap if the right-hand sides of the overlapping instances coincide for the overlapping types. More formally, two instance declarations overlap if there is a substitution that makes the left-hand sides of the instances syntactically the same. Whenever that is the case, the right-hand sides of the instances must also be syntactically equal under the same substitution. This condition is independent of whether the type family is associated or not, and it is not only a matter of consistency, but one of type safety.<br />
<br />
Here are two examples to illustrate the condition under which overlap is permitted.<br />
<haskell><br />
type instance F (a, Int) = [a]<br />
type instance F (Int, b) = [b] -- overlap permitted<br />
<br />
type instance G (a, Int) = [a]<br />
type instance G (Char, a) = [a] -- ILLEGAL overlap, as [Char] /= [Int]<br />
</haskell><br />
<br />
==== Decidability ====<br />
<br />
In order to guarantee that type inference in the presence of type families is decidable, we need to place a number of additional restrictions on the formation of type instance declarations (c.f., Definition 5 (Relaxed Conditions) of [http://www.cse.unsw.edu.au/~chak/papers/SPCS08.html Type Checking with Open Type Functions]). Instance declarations have the general form<br />
<haskell><br />
type instance F t1 .. tn = t<br />
</haskell><br />
where we require that for every type family application <hask>(G s1 .. sm)</hask> in <hask>t</hask>, <br />
# <hask>s1 .. sm</hask> do not contain any type family constructors,<br />
# the total number of symbols (data type constructors and type variables) in <hask>s1 .. sm</hask> is strictly smaller than in <hask>t1 .. tn</hask>, and<br />
# for every type variable <hask>a</hask>, <hask>a</hask> occurs in <hask>s1 .. sm</hask> at most as often as in <hask>t1 .. tn</hask>.<br />
These restrictions are easily verified and ensure termination of type inference. However, they are not sufficient to guarantee completeness of type inference in the presence of, so called, ''loopy equalities'', such as <hask>a ~ [F a]</hask>, where a recursive occurrence of a type variable is underneath a family application and data constructor application - see the above mentioned paper for details. <br />
<br />
If the option <tt>-XUndecidableInstances</tt> is passed to the compiler, the above restrictions are not enforced and it is on the programmer to ensure termination of the normalisation of type families during type inference.<br />
<br />
=== Equality constraints ===<br />
<br />
Type context can include equality constraints of the form <hask>t1 ~ t2</hask>, which denote that the types <hask>t1</hask> and <hask>t2</hask> need to be the same. In the presence of type families, whether two types are equal cannot generally be decided locally. Hence, the contexts of function signatures may include equality constraints, as in the following example:<br />
<haskell><br />
sumCollects :: (Collects c1, Collects c2, Elem c1 ~ Elem c2) => c1 -> c2 -> c2<br />
</haskell><br />
where we require that the element type of <hask>c1</hask> and <hask>c2</hask> are the same. In general, the types <hask>t1</hask> and <hask>t2</hask> of an equality constraint may be arbitrary monotypes; i.e., they may not contain any quantifiers, independent of whether higher-rank types are otherwise enabled.<br />
<br />
Equality constraints can also appear in class and instance contexts. The former enable a simple translation of programs using functional dependencies into programs using family synonyms instead. The general idea is to rewrite a class declaration of the form<br />
<haskell><br />
class C a b | a -> b<br />
</haskell><br />
to<br />
<haskell><br />
class (F a ~ b) => C a b where<br />
type F a<br />
</haskell><br />
That is, we represent every functional dependency (FD) <hask>a1 .. an -> b</hask> by an FD type family <hask>F a1 .. an</hask> and a superclass context equality <hask>F a1 .. an ~ b</hask>, essentially giving a name to the functional dependency. In class instances, we define the type instances of FD families in accordance with the class head. Method signatures are not affected by that process.<br />
<br />
NB: Equalities in superclass contexts are not fully implemented in the GHC 6.10 branch.<br />
<br />
== Frequently asked questions ==<br />
<br />
=== Injectivity, type inference, and ambiguity ===<br />
<br />
A common problem is this<br />
<haskell><br />
type family F a<br />
<br />
f :: F a -> F a<br />
f = undefined<br />
<br />
g :: F Int -> F Int<br />
g x = f x<br />
</haskell><br />
The compiler complains about the definition of <tt>g</tt> saying<br />
<haskell><br />
Couldn't match expected type `F Int' against inferred type `F a1'<br />
</haskell><br />
In type-checking <tt>g</tt>'s right hand side GHC discovers (by instantiating <tt>f</tt>'s type with a fresh type variable) that it has type <tt>F a1 -> F a1</tt> for some as-yet-unknown type <tt>a1</tt>. Now it tries to make the inferred type match <tt>g</tt>'s type signature. Well, you say, just make <tt>a1</tt> equal to <tt>Int</tt> and you are done. True, but what if there were these instances<br />
<haskell><br />
type instance F Int = Bool<br />
type instance F Char = Bool<br />
</haskell><br />
Then making <tt>a1</tt> equal to <tt>Char</tt> would ''also'' make the two types equal. Because there is (potentially) more than one choice, the program is rejected.<br />
<br />
However (and confusingly) if you omit the type signature on <tt>g</tt> altogether, thus<br />
<haskell><br />
f :: F a -> F a<br />
f = undefined<br />
<br />
g x = f x<br />
</haskell><br />
GHC will happily infer the type <tt>g :: F a -> F a</tt>. But you can't ''write'' that type signature or, indeed, the more specific one above. (Arguably this behaviour, where GHC ''infers'' a type it can't ''check'', is very confusing. I suppose we could make GHC reject both programs, with and without type signatures.)<br />
<br />
'''What is the problem?''' The nub of the issue is this: knowing that <tt>F t1</tt>=<tt>F t2</tt> does ''not'' imply that <tt>t1</tt> = <tt>t2</tt>.<br />
The difficulty is that the type function <tt>F</tt> need not be ''injective''; it can map two distinct types to the same type. For an injective type constructor like <tt>Maybe</tt>, if we know that <tt>Maybe t1</tt> = <tt>Maybe t2</tt>, then we know that <tt>t1</tt> = <tt>t2</tt>. But not so for non-injective type functions.<br />
<br />
The problem starts with <tt>f</tt>. Its type is ''ambiguous''; even if I know the argument and result types for <tt>f</tt>, I cannot use that to find the type at which <tt>a</tt> should be instantiated. (So arguably, <tt>f</tt> should be rejected as having an ambiguous type, and probably will be in future.) The situation is well known in type classes: <br />
<haskell><br />
bad :: (Read a, Show a) => String -> String<br />
bad x = show (read x)<br />
</haskell><br />
At a call of <tt>bad</tt> one cannot tell at what type <tt>a</tt> should be instantiated.<br />
<br />
The only solution is to avoid ambiguous types. In the type signature of a function, <br />
* Ensure that every type variable occurs in the part after the "<tt>=></tt>"<br />
* Ensure that every type variable appears at least once outside a type function call.<br />
Alternatively, you can use data families, which create new types and are therefore injective. The following code works:<br />
<br />
<haskell>data family F a<br />
<br />
f :: F a -> F a<br />
f = undefined<br />
<br />
g :: F Int -> F Int<br />
g x = f x</haskell><br />
<br />
== References ==<br />
<br />
* [http://www.cse.unsw.edu.au/~chak/papers/CKPM05.html Associated Types with Class.] Manuel M. T. Chakravarty, Gabriele Keller, Simon Peyton Jones, and Simon Marlow. In ''Proceedings of The 32nd Annual ACM SIGPLAN-SIGACT Symposium on Principles of Programming Languages (POPL'05)'', pages 1-13, ACM Press, 2005.<br />
* [http://www.cse.unsw.edu.au/~chak/papers/CKP05.html Associated Type Synonyms.] 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 />
* [http://www.cse.unsw.edu.au/~chak/papers/SCPD07.html System F with Type Equality Coercions.] Martin Sulzmann, Manuel M. T. Chakravarty, Simon Peyton Jones, and Kevin Donnelly. In ''Proceedings of The Third ACM SIGPLAN Workshop on Types in Language Design and Implementation'', ACM Press, 2007.<br />
* [http://www.cse.unsw.edu.au/~chak/papers/SPCS08.html Type Checking With Open Type Functions.] Tom Schrijvers, Simon Peyton-Jones, Manuel M. T. Chakravarty, Martin Sulzmann. In ''Proceedings of The 13th ACM SIGPLAN International Conference on Functional Programming'', ACM Press, pages 51-62, 2008.<br />
* [[Simonpj/Talk:FunWithTypeFuns | Fun with Type Functions]] Oleg Kiselyov, Simon Peyton Jones, Chung-chieh Shan (the source for this paper can be found at http://patch-tag.com/r/schoenfinkel/typefunctions/wiki ) <br />
<br />
[[Category:Type-level programming]]<br />
[[Category:Language extensions]]<br />
[[Category:GHC|Indexed types]]</div>Simonpjhttps://wiki.haskell.org/index.php?title=GHC/Type_families&diff=40687GHC/Type families2011-06-29T12:54:21Z<p>Simonpj: /* Injectivity, type inference, and ambiguity */</p>
<hr />
<div>Indexed type families, or '''type families''' for short, are a Haskell extension supporting ad-hoc overloading of data types. Type families are parametric types that can be assigned specialized representations based on the type parameters they are instantiated with. They are the data type analogue of [[Type class|type classes]]: families are used to define overloaded ''data'' in the same way that classes are used to define overloaded ''functions''. Type families are useful for generic programming, for creating highly parameterised library interfaces, and for creating interfaces with enhanced static information, much like dependent types.<br />
<br />
Type families come in two flavors: ''data families'' and ''type synonym families''. Data families are the indexed form of data and newtype definitions. Type synonym families are the indexed form of type synonyms. Each of these flavors can be defined in a standalone manner or ''associated'' with a type class. Standalone definitions are more general, while associated types can more clearly express how a type is used and lead to better error messages.<br />
<br />
''NB: see also Simon's [http://hackage.haskell.org/trac/ghc/blog/LetGeneralisationInGhc7 blog entry on let generalisation] for a significant change in the policy for let generalisation, driven by the type family extension. In brief: a few programs will puzzlingly fail to compile with <tt>-XTypeFamilies</tt> even though the code is legal Haskell 98.''<br />
<br />
== What are type families? ==<br />
<br />
The concept of a type family comes from type theory. An indexed type family in type theory is a partial function at the type level. Applying the function to parameters (called ''type indices'') yields a type. Type families permit a program to compute what data constructors it will operate on, rather than having them fixed statically (as with simple type systems) or treated as opaque unknowns (as with parametrically polymorphic types).<br />
<br />
Type families are to vanilla data types what type class methods are to regular functions. Vanilla polymorphic data types and functions have a single definition, which is used at all type instances. Classes and type families, on the other hand, have an interface definition and any number of instance definitions. A type family's interface definition declares its [[kind]] and its arity, or the number of type indices it takes. Instance definitions define the type family over some part of the domain.<br />
<br />
As a simple example of how type families differ from ordinary parametric data types, consider a strict list type. We can represent a list of <hask>Char</hask> in the usual way, with cons cells. We can do the same thing to represent a list of <hask>()</hask>, but since a strict <hask>()</hask> value carries no useful information, it would be more efficient to just store the length of the list. This can't be done with an ordinary parametric data type, because the data constructors used to represent the list would depend on the list's type parameter: if it's <hask>Char</hask> then the list consists of cons cells; if it's <hask>()</hask>, then the list consists of a single integer. We basically want to select between two different data types based on a type parameter. Using type families, this list type could be declared as follows:<br />
<br />
<haskell><br />
-- Declare a list-like data family<br />
data family XList a<br />
<br />
-- Declare a list-like instance for Char<br />
data instance XList Char = XCons !Char !(XList Char) | XNil<br />
<br />
-- Declare a number-like instance for ()<br />
data instance XList () = XListUnit !Int<br />
</haskell><br />
<br />
The right-hand sides of the two <code>data instance</code> declarations are exactly ordinary data definitions. However, they define two instances of the same parametric data type, <hask>XList Char</hask> and <hask>XList ()</hask>, whereas ordinary data declarations define completely unrelated types. A recent [[Simonpj/Talk:FunWithTypeFuns|tutorial paper]] has more in-depth examples of programming with type families. <br />
<br />
GADTs bear some similarity to type families, in the sense that they allow a parametric type's constructors to depend on the type's parameters. However, all GADT constructors must be defined in one place, whereas type families can be extended. Functional dependences are similar to type families, and many type classes that use functional dependences can be equivalently expressed with type families. Type families provide a more functional style of type-level programming than the relational style of functional dependences.<br />
<br />
== What do I need to use type families? ==<br />
<br />
Type families are a GHC extension enabled with the <code>-XTypeFamilies</code> flag or the <code>{-# LANGUAGE TypeFamilies #-}</code> pragma. The first stable release of GHC that properly supports type families is 6.10.1. (The 6.8 release included an early partial implementation, but its use is deprecated.) Please [http://hackage.haskell.org/trac/ghc/query?status=new&status=assigned&status=reopened&group=priority&type=bug&order=id&desc=1 report bugs] via the GHC bug tracker, ideally accompanied by a small example program that demonstrates the problem. Use the [mailto:glasgow-haskell-users@haskell.org GHC mailing list] for questions or for a discussion of this language extension and its description on this wiki page.<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-families.html#data-family-declarations ''kind signature''] (here <hask>* -> *</hask>) for the associated data type <hask>GMap k</hask> - analogous 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.IntMap</hask>, thusly:<br />
<haskell><br />
instance GMapKey Int where<br />
data GMap Int v = GMapInt (Data.IntMap.IntMap v)<br />
empty = GMapInt Data.IntMap.empty<br />
lookup k (GMapInt m) = Data.IntMap.lookup k m<br />
insert k v (GMapInt m) = GMapInt (Data.IntMap.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 fundamental 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 />
Next, 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 b) v (GMapEither gm1 gm2) = GMapEither gm1 (insert b v gm2)<br />
</haskell><br />
If you find this code algorithmically surprising, I'd suggest to have a look at [http://www.cs.ox.ac.uk/ralf.hinze/publications/index.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 querying 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 source code[http://darcs.haskell.org/testsuite/tests/ghc-regress/indexed-types/should_run/GMapAssoc.hs] for <hask>GMap</hask> from GHC's test suite.<br />
<br />
== Detailed definition of data families ==<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-indices to coincide with the class parameters. However, the latter 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> keyword. 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-indices. 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. In other words: '''the named type parameters of the data declaration must be a permutation of a subset of the class variables'''. <br />
<br />
Example is admissible:<br />
<haskell><br />
class C a b c where { data T c a :: * } -- OK<br />
class C a b c where { data T a a :: * } -- Bad: repeated variable<br />
class D a where { data T a x :: * } -- Bad: x is not a class variable<br />
class D a where { data T a :: * -> * } -- OK<br />
</haskell><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, but may not contain forall types or type synonym families. However, data families are generally allowed in type parameters, and type synonyms are allowed as long as they are fully applied and expand to a type that is itself admissible - exactly as this is required for occurrences of type synonyms in class instance parameters. 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 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 />
nonsense :: T a -> Int<br />
nonsense A = 1 -- WRONG: These two equations together...<br />
nonsense 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 - 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 indices corresponding to class parameters must be identical to the type given in the instance head; here this is the 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 instance 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 />
==== Scoping of class parameters ====<br />
<br />
In the case of multi-parameter type classes, the visibility of class parameters in the right-hand side of associated family instances depends ''solely'' on the parameters of the data family. As an example, consider the simple class declaration<br />
<haskell><br />
class C a b where<br />
data T a<br />
</haskell><br />
Only one of the two class parameters is a parameter to the data family. Hence, the following instance declaration is invalid:<br />
<haskell><br />
instance C [c] d where<br />
data T [c] = MkT (c, d) -- WRONG!! 'd' is not in scope<br />
</haskell><br />
Here, the right-hand side of the data instance mentions the type variable <hask>d</hask> that does not occur in its left-hand side. We cannot admit such data instances as they would compromise type safety.<br />
<br />
==== Type class instances of family 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 implicitly 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 is 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>GMapEither</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 />
== An associated type synonym example ==<br />
<br />
Type synonym families are an alternative to functional dependencies, which makes functional dependency examples well suited to introduce type synonym families. In fact, type families are a more functional way to express the same as functional dependencies (despite the name!), as they replace the relational notation of functional dependencies by an expression-oriented notation; i.e., functions on types are really represented by functions and not relations.<br />
<br />
=== The <hask>class</hask> declaration ===<br />
<br />
Here's an example from Mark Jones' seminal paper on functional dependencies:<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 />
Instead of the multi-parameter type class, we use a single parameter class, and the parameter <hask>e</hask><br />
turned into an associated type synonym <hask>Elem ce</hask>.<br />
<br />
=== An <hask>instance</hask>===<br />
<br />
Instances change correspondingly. An instance of the two-parameter class<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) <br />
| e == x = True<br />
| otherwise = member e xs<br />
toList l = l<br />
</haskell><br />
becomes an instance of a single-parameter class, where the dependent type parameter turns into an associated type instance declaration:<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) <br />
| 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 />
== Detailed definition of type synonym families ==<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-indices to coincide with the class parameters. However, the latter 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 />
Parameters can also be given explicit kind signatures if needed. We call the number of parameters in a type family declaration, the family's arity, and all applications of a type family must be fully saturated w.r.t. to that arity. This requirement is unlike ordinary type synonyms and it implies that the kind of a type family is not sufficient to determine a family's arity, and hence in general, also insufficient to determine whether a type family application is well formed. As an example, consider the following declaration:<br />
<haskell><br />
type family F a b :: * -> * -- F's arity is 2, <br />
-- although its overall kind is * -> * -> * -> *<br />
</haskell><br />
Given this declaration the following are examples of well-formed and malformed types:<br />
<haskell><br />
F Char [Int] -- OK! Kind: * -> *<br />
F Char [Int] Bool -- OK! Kind: *<br />
F IO Bool -- WRONG: kind mismatch in the first argument<br />
F Bool -- WRONG: unsaturated application<br />
</haskell><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 />
Exactly as in the case of an associated data declaration, '''the named type parameters must be a permutation of a subset of the class parameters'''. Examples<br />
<haskell><br />
class C a b c where { type T c a :: * } -- OK<br />
class D a where { type T a x :: * } -- No: x is not a class parameter<br />
class D a where { type T a :: * -> * } -- OK<br />
</haskell><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, but may not contain forall types or type synonym families. However, data families are generally allowed, and type synonyms are allowed as long as they are fully applied and expand to a type that is admissible - these are the exact same requirements as for data instances. For example, the <hask>[e]</hask> instance for <hask>Elem</hask> is<br />
<haskell><br />
type instance Elem [e] = e<br />
</haskell><br />
<br />
A type family instance declaration must satisfy the following rules:<br />
* An appropriate family declaration is in scope - just like class instances require the class declaration to be visible. <br />
* The instance declaration conforms to the kind determined by its family declaration<br />
* The number of type parameters in an instance declaration matches the number of type parameters in the family declaration.<br />
* The right-hand side of a type instance must be a monotype (i.e., it may not include foralls) and after the expansion of all saturated vanilla type synonyms, no synonyms, except family synonyms may remain.<br />
<br />
Here are some examples of admissible and illegal type instances:<br />
<haskell><br />
type family F a :: *<br />
type instance F [Int] = Int -- OK!<br />
type instance F String = Char -- OK!<br />
type instance F (F a) = a -- WRONG: type parameter mentions a type family<br />
type instance F (forall a. (a, b)) = b -- WRONG: a forall type appears in a type parameter<br />
type instance F Float = forall a.a -- WRONG: right-hand side may not be a forall type<br />
<br />
type family G a b :: * -> *<br />
type instance G Int = (,) -- WRONG: must be two type parameters<br />
type instance G Int Char Float = Double -- WRONG: must be two type parameters<br />
</haskell><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 instance 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 only overlap if the right-hand sides of the overlapping instances coincide for the overlapping types. More formally, two instance declarations overlap if there is a substitution that makes the left-hand sides of the instances syntactically the same. Whenever that is the case, the right-hand sides of the instances must also be syntactically equal under the same substitution. This condition is independent of whether the type family is associated or not, and it is not only a matter of consistency, but one of type safety.<br />
<br />
Here are two examples to illustrate the condition under which overlap is permitted.<br />
<haskell><br />
type instance F (a, Int) = [a]<br />
type instance F (Int, b) = [b] -- overlap permitted<br />
<br />
type instance G (a, Int) = [a]<br />
type instance G (Char, a) = [a] -- ILLEGAL overlap, as [Char] /= [Int]<br />
</haskell><br />
<br />
==== Decidability ====<br />
<br />
In order to guarantee that type inference in the presence of type families is decidable, we need to place a number of additional restrictions on the formation of type instance declarations (c.f., Definition 5 (Relaxed Conditions) of [http://www.cse.unsw.edu.au/~chak/papers/SPCS08.html Type Checking with Open Type Functions]). Instance declarations have the general form<br />
<haskell><br />
type instance F t1 .. tn = t<br />
</haskell><br />
where we require that for every type family application <hask>(G s1 .. sm)</hask> in <hask>t</hask>, <br />
# <hask>s1 .. sm</hask> do not contain any type family constructors,<br />
# the total number of symbols (data type constructors and type variables) in <hask>s1 .. sm</hask> is strictly smaller than in <hask>t1 .. tn</hask>, and<br />
# for every type variable <hask>a</hask>, <hask>a</hask> occurs in <hask>s1 .. sm</hask> at most as often as in <hask>t1 .. tn</hask>.<br />
These restrictions are easily verified and ensure termination of type inference. However, they are not sufficient to guarantee completeness of type inference in the presence of, so called, ''loopy equalities'', such as <hask>a ~ [F a]</hask>, where a recursive occurrence of a type variable is underneath a family application and data constructor application - see the above mentioned paper for details. <br />
<br />
If the option <tt>-XUndecidableInstances</tt> is passed to the compiler, the above restrictions are not enforced and it is on the programmer to ensure termination of the normalisation of type families during type inference.<br />
<br />
=== Equality constraints ===<br />
<br />
Type context can include equality constraints of the form <hask>t1 ~ t2</hask>, which denote that the types <hask>t1</hask> and <hask>t2</hask> need to be the same. In the presence of type families, whether two types are equal cannot generally be decided locally. Hence, the contexts of function signatures may include equality constraints, as in the following example:<br />
<haskell><br />
sumCollects :: (Collects c1, Collects c2, Elem c1 ~ Elem c2) => c1 -> c2 -> c2<br />
</haskell><br />
where we require that the element type of <hask>c1</hask> and <hask>c2</hask> are the same. In general, the types <hask>t1</hask> and <hask>t2</hask> of an equality constraint may be arbitrary monotypes; i.e., they may not contain any quantifiers, independent of whether higher-rank types are otherwise enabled.<br />
<br />
Equality constraints can also appear in class and instance contexts. The former enable a simple translation of programs using functional dependencies into programs using family synonyms instead. The general idea is to rewrite a class declaration of the form<br />
<haskell><br />
class C a b | a -> b<br />
</haskell><br />
to<br />
<haskell><br />
class (F a ~ b) => C a b where<br />
type F a<br />
</haskell><br />
That is, we represent every functional dependency (FD) <hask>a1 .. an -> b</hask> by an FD type family <hask>F a1 .. an</hask> and a superclass context equality <hask>F a1 .. an ~ b</hask>, essentially giving a name to the functional dependency. In class instances, we define the type instances of FD families in accordance with the class head. Method signatures are not affected by that process.<br />
<br />
NB: Equalities in superclass contexts are not fully implemented in the GHC 6.10 branch.<br />
<br />
== Frequently asked questions ==<br />
<br />
=== Injectivity, type inference, and ambiguity ===<br />
<br />
A common problem is this<br />
<haskell><br />
type family F a<br />
<br />
f :: F a -> F a<br />
f = undefined<br />
<br />
g :: F Int -> F Int<br />
g x = f x<br />
</haskell><br />
The compiler complains about the definition of <tt>g</tt> saying<br />
<haskell><br />
Couldn't match expected type `F Int' against inferred type `F a1'<br />
</haskell><br />
In type-checking <tt>g</tt>'s right hand side GHC discovers (by instantiating <tt>f</tt>'s type with a fresh type variable) that it has type <tt>F a1 -> F a1</tt> for some as-yet-unknown type <tt>a1</tt>. Now it tries to make the inferred type match <tt>g</tt>'s type signature. Well, you say, just make <tt>a1</tt> equal to <tt>Int</tt> and you are done. True, but what if there were these instances<br />
<haskell><br />
type instance F Int = Bool<br />
type instance F Char = Bool<br />
</haskell><br />
Then making <tt>a1</tt> equal to <tt>Char</tt> would ''also'' make the two types equal. Because there is (potentially) more than one choice, the program is rejected.<br />
<br />
However (and confusingly) if you omit the type signature on <tt>g</tt> altogether, thus<br />
<haskell><br />
f :: F a -> F a<br />
f = undefined<br />
<br />
g x = f x<br />
</haskell><br />
GHC will happily infer the type <tt>g :: F a -> F a</tt>. But you can't ''write'' that type signature (or, indeed, the more specific one above).<br />
<br />
'''What is the problem?''' The nub of the issue is this: knowing that <tt>F t1</tt>=<tt>F t2</tt> does ''not'' imply that <tt>t1</tt> = <tt>t2</tt>.<br />
The difficulty is that the type function <tt>F</tt> need not be ''injective''; it can map two distinct types to the same type. For an injective type constructor like <tt>Maybe</tt>, if we know that <tt>Maybe t1</tt> = <tt>Maybe t2</tt>, then we know that <tt>t1</tt> = <tt>t2</tt>. But not so for non-injective type functions.<br />
<br />
The problem starts with <tt>f</tt>. Its type is ''ambiguous''; even if I know the argument and result types for <tt>f</tt>, I cannot use that to find the type at which <tt>a</tt> should be instantiated. (So arguably, <tt>f</tt> should be rejected as having an ambiguous type, and probably will be in future.) The situation is well known in type classes: <br />
<haskell><br />
bad :: (Read a, Show a) => String -> String<br />
bad x = show (read x)<br />
</haskell><br />
At a call of <tt>bad</tt> one cannot tell at what type <tt>a</tt> should be instantiated.<br />
<br />
The only solution is to avoid ambiguous types. In the type signature of a function, <br />
* Ensure that every type variable occurs in the part after the "<tt>=></tt>"<br />
* Ensure that every type variable appears at least once outside a type function call.<br />
Alternatively, you can use data families, which create new types and are therefore injective. The following code works:<br />
<br />
<haskell>data family F a<br />
<br />
f :: F a -> F a<br />
f = undefined<br />
<br />
g :: F Int -> F Int<br />
g x = f x</haskell><br />
<br />
== References ==<br />
<br />
* [http://www.cse.unsw.edu.au/~chak/papers/CKPM05.html Associated Types with Class.] Manuel M. T. Chakravarty, Gabriele Keller, Simon Peyton Jones, and Simon Marlow. In ''Proceedings of The 32nd Annual ACM SIGPLAN-SIGACT Symposium on Principles of Programming Languages (POPL'05)'', pages 1-13, ACM Press, 2005.<br />
* [http://www.cse.unsw.edu.au/~chak/papers/CKP05.html Associated Type Synonyms.] 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 />
* [http://www.cse.unsw.edu.au/~chak/papers/SCPD07.html System F with Type Equality Coercions.] Martin Sulzmann, Manuel M. T. Chakravarty, Simon Peyton Jones, and Kevin Donnelly. In ''Proceedings of The Third ACM SIGPLAN Workshop on Types in Language Design and Implementation'', ACM Press, 2007.<br />
* [http://www.cse.unsw.edu.au/~chak/papers/SPCS08.html Type Checking With Open Type Functions.] Tom Schrijvers, Simon Peyton-Jones, Manuel M. T. Chakravarty, Martin Sulzmann. In ''Proceedings of The 13th ACM SIGPLAN International Conference on Functional Programming'', ACM Press, pages 51-62, 2008.<br />
* [[Simonpj/Talk:FunWithTypeFuns | Fun with Type Functions]] Oleg Kiselyov, Simon Peyton Jones, Chung-chieh Shan (the source for this paper can be found at http://patch-tag.com/r/schoenfinkel/typefunctions/wiki ) <br />
<br />
[[Category:Type-level programming]]<br />
[[Category:Language extensions]]<br />
[[Category:GHC|Indexed types]]</div>Simonpjhttps://wiki.haskell.org/index.php?title=GHC/Type_families&diff=40686GHC/Type families2011-06-29T12:53:50Z<p>Simonpj: /* Injectivity, type inference, and ambiguity */</p>
<hr />
<div>Indexed type families, or '''type families''' for short, are a Haskell extension supporting ad-hoc overloading of data types. Type families are parametric types that can be assigned specialized representations based on the type parameters they are instantiated with. They are the data type analogue of [[Type class|type classes]]: families are used to define overloaded ''data'' in the same way that classes are used to define overloaded ''functions''. Type families are useful for generic programming, for creating highly parameterised library interfaces, and for creating interfaces with enhanced static information, much like dependent types.<br />
<br />
Type families come in two flavors: ''data families'' and ''type synonym families''. Data families are the indexed form of data and newtype definitions. Type synonym families are the indexed form of type synonyms. Each of these flavors can be defined in a standalone manner or ''associated'' with a type class. Standalone definitions are more general, while associated types can more clearly express how a type is used and lead to better error messages.<br />
<br />
''NB: see also Simon's [http://hackage.haskell.org/trac/ghc/blog/LetGeneralisationInGhc7 blog entry on let generalisation] for a significant change in the policy for let generalisation, driven by the type family extension. In brief: a few programs will puzzlingly fail to compile with <tt>-XTypeFamilies</tt> even though the code is legal Haskell 98.''<br />
<br />
== What are type families? ==<br />
<br />
The concept of a type family comes from type theory. An indexed type family in type theory is a partial function at the type level. Applying the function to parameters (called ''type indices'') yields a type. Type families permit a program to compute what data constructors it will operate on, rather than having them fixed statically (as with simple type systems) or treated as opaque unknowns (as with parametrically polymorphic types).<br />
<br />
Type families are to vanilla data types what type class methods are to regular functions. Vanilla polymorphic data types and functions have a single definition, which is used at all type instances. Classes and type families, on the other hand, have an interface definition and any number of instance definitions. A type family's interface definition declares its [[kind]] and its arity, or the number of type indices it takes. Instance definitions define the type family over some part of the domain.<br />
<br />
As a simple example of how type families differ from ordinary parametric data types, consider a strict list type. We can represent a list of <hask>Char</hask> in the usual way, with cons cells. We can do the same thing to represent a list of <hask>()</hask>, but since a strict <hask>()</hask> value carries no useful information, it would be more efficient to just store the length of the list. This can't be done with an ordinary parametric data type, because the data constructors used to represent the list would depend on the list's type parameter: if it's <hask>Char</hask> then the list consists of cons cells; if it's <hask>()</hask>, then the list consists of a single integer. We basically want to select between two different data types based on a type parameter. Using type families, this list type could be declared as follows:<br />
<br />
<haskell><br />
-- Declare a list-like data family<br />
data family XList a<br />
<br />
-- Declare a list-like instance for Char<br />
data instance XList Char = XCons !Char !(XList Char) | XNil<br />
<br />
-- Declare a number-like instance for ()<br />
data instance XList () = XListUnit !Int<br />
</haskell><br />
<br />
The right-hand sides of the two <code>data instance</code> declarations are exactly ordinary data definitions. However, they define two instances of the same parametric data type, <hask>XList Char</hask> and <hask>XList ()</hask>, whereas ordinary data declarations define completely unrelated types. A recent [[Simonpj/Talk:FunWithTypeFuns|tutorial paper]] has more in-depth examples of programming with type families. <br />
<br />
GADTs bear some similarity to type families, in the sense that they allow a parametric type's constructors to depend on the type's parameters. However, all GADT constructors must be defined in one place, whereas type families can be extended. Functional dependences are similar to type families, and many type classes that use functional dependences can be equivalently expressed with type families. Type families provide a more functional style of type-level programming than the relational style of functional dependences.<br />
<br />
== What do I need to use type families? ==<br />
<br />
Type families are a GHC extension enabled with the <code>-XTypeFamilies</code> flag or the <code>{-# LANGUAGE TypeFamilies #-}</code> pragma. The first stable release of GHC that properly supports type families is 6.10.1. (The 6.8 release included an early partial implementation, but its use is deprecated.) Please [http://hackage.haskell.org/trac/ghc/query?status=new&status=assigned&status=reopened&group=priority&type=bug&order=id&desc=1 report bugs] via the GHC bug tracker, ideally accompanied by a small example program that demonstrates the problem. Use the [mailto:glasgow-haskell-users@haskell.org GHC mailing list] for questions or for a discussion of this language extension and its description on this wiki page.<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-families.html#data-family-declarations ''kind signature''] (here <hask>* -> *</hask>) for the associated data type <hask>GMap k</hask> - analogous 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.IntMap</hask>, thusly:<br />
<haskell><br />
instance GMapKey Int where<br />
data GMap Int v = GMapInt (Data.IntMap.IntMap v)<br />
empty = GMapInt Data.IntMap.empty<br />
lookup k (GMapInt m) = Data.IntMap.lookup k m<br />
insert k v (GMapInt m) = GMapInt (Data.IntMap.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 fundamental 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 />
Next, 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 b) v (GMapEither gm1 gm2) = GMapEither gm1 (insert b v gm2)<br />
</haskell><br />
If you find this code algorithmically surprising, I'd suggest to have a look at [http://www.cs.ox.ac.uk/ralf.hinze/publications/index.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 querying 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 source code[http://darcs.haskell.org/testsuite/tests/ghc-regress/indexed-types/should_run/GMapAssoc.hs] for <hask>GMap</hask> from GHC's test suite.<br />
<br />
== Detailed definition of data families ==<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-indices to coincide with the class parameters. However, the latter 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> keyword. 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-indices. 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. In other words: '''the named type parameters of the data declaration must be a permutation of a subset of the class variables'''. <br />
<br />
Example is admissible:<br />
<haskell><br />
class C a b c where { data T c a :: * } -- OK<br />
class C a b c where { data T a a :: * } -- Bad: repeated variable<br />
class D a where { data T a x :: * } -- Bad: x is not a class variable<br />
class D a where { data T a :: * -> * } -- OK<br />
</haskell><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, but may not contain forall types or type synonym families. However, data families are generally allowed in type parameters, and type synonyms are allowed as long as they are fully applied and expand to a type that is itself admissible - exactly as this is required for occurrences of type synonyms in class instance parameters. 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 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 />
nonsense :: T a -> Int<br />
nonsense A = 1 -- WRONG: These two equations together...<br />
nonsense 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 - 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 indices corresponding to class parameters must be identical to the type given in the instance head; here this is the 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 instance 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 />
==== Scoping of class parameters ====<br />
<br />
In the case of multi-parameter type classes, the visibility of class parameters in the right-hand side of associated family instances depends ''solely'' on the parameters of the data family. As an example, consider the simple class declaration<br />
<haskell><br />
class C a b where<br />
data T a<br />
</haskell><br />
Only one of the two class parameters is a parameter to the data family. Hence, the following instance declaration is invalid:<br />
<haskell><br />
instance C [c] d where<br />
data T [c] = MkT (c, d) -- WRONG!! 'd' is not in scope<br />
</haskell><br />
Here, the right-hand side of the data instance mentions the type variable <hask>d</hask> that does not occur in its left-hand side. We cannot admit such data instances as they would compromise type safety.<br />
<br />
==== Type class instances of family 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 implicitly 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 is 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>GMapEither</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 />
== An associated type synonym example ==<br />
<br />
Type synonym families are an alternative to functional dependencies, which makes functional dependency examples well suited to introduce type synonym families. In fact, type families are a more functional way to express the same as functional dependencies (despite the name!), as they replace the relational notation of functional dependencies by an expression-oriented notation; i.e., functions on types are really represented by functions and not relations.<br />
<br />
=== The <hask>class</hask> declaration ===<br />
<br />
Here's an example from Mark Jones' seminal paper on functional dependencies:<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 />
Instead of the multi-parameter type class, we use a single parameter class, and the parameter <hask>e</hask><br />
turned into an associated type synonym <hask>Elem ce</hask>.<br />
<br />
=== An <hask>instance</hask>===<br />
<br />
Instances change correspondingly. An instance of the two-parameter class<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) <br />
| e == x = True<br />
| otherwise = member e xs<br />
toList l = l<br />
</haskell><br />
becomes an instance of a single-parameter class, where the dependent type parameter turns into an associated type instance declaration:<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) <br />
| 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 />
== Detailed definition of type synonym families ==<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-indices to coincide with the class parameters. However, the latter 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 />
Parameters can also be given explicit kind signatures if needed. We call the number of parameters in a type family declaration, the family's arity, and all applications of a type family must be fully saturated w.r.t. to that arity. This requirement is unlike ordinary type synonyms and it implies that the kind of a type family is not sufficient to determine a family's arity, and hence in general, also insufficient to determine whether a type family application is well formed. As an example, consider the following declaration:<br />
<haskell><br />
type family F a b :: * -> * -- F's arity is 2, <br />
-- although its overall kind is * -> * -> * -> *<br />
</haskell><br />
Given this declaration the following are examples of well-formed and malformed types:<br />
<haskell><br />
F Char [Int] -- OK! Kind: * -> *<br />
F Char [Int] Bool -- OK! Kind: *<br />
F IO Bool -- WRONG: kind mismatch in the first argument<br />
F Bool -- WRONG: unsaturated application<br />
</haskell><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 />
Exactly as in the case of an associated data declaration, '''the named type parameters must be a permutation of a subset of the class parameters'''. Examples<br />
<haskell><br />
class C a b c where { type T c a :: * } -- OK<br />
class D a where { type T a x :: * } -- No: x is not a class parameter<br />
class D a where { type T a :: * -> * } -- OK<br />
</haskell><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, but may not contain forall types or type synonym families. However, data families are generally allowed, and type synonyms are allowed as long as they are fully applied and expand to a type that is admissible - these are the exact same requirements as for data instances. For example, the <hask>[e]</hask> instance for <hask>Elem</hask> is<br />
<haskell><br />
type instance Elem [e] = e<br />
</haskell><br />
<br />
A type family instance declaration must satisfy the following rules:<br />
* An appropriate family declaration is in scope - just like class instances require the class declaration to be visible. <br />
* The instance declaration conforms to the kind determined by its family declaration<br />
* The number of type parameters in an instance declaration matches the number of type parameters in the family declaration.<br />
* The right-hand side of a type instance must be a monotype (i.e., it may not include foralls) and after the expansion of all saturated vanilla type synonyms, no synonyms, except family synonyms may remain.<br />
<br />
Here are some examples of admissible and illegal type instances:<br />
<haskell><br />
type family F a :: *<br />
type instance F [Int] = Int -- OK!<br />
type instance F String = Char -- OK!<br />
type instance F (F a) = a -- WRONG: type parameter mentions a type family<br />
type instance F (forall a. (a, b)) = b -- WRONG: a forall type appears in a type parameter<br />
type instance F Float = forall a.a -- WRONG: right-hand side may not be a forall type<br />
<br />
type family G a b :: * -> *<br />
type instance G Int = (,) -- WRONG: must be two type parameters<br />
type instance G Int Char Float = Double -- WRONG: must be two type parameters<br />
</haskell><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 instance 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 only overlap if the right-hand sides of the overlapping instances coincide for the overlapping types. More formally, two instance declarations overlap if there is a substitution that makes the left-hand sides of the instances syntactically the same. Whenever that is the case, the right-hand sides of the instances must also be syntactically equal under the same substitution. This condition is independent of whether the type family is associated or not, and it is not only a matter of consistency, but one of type safety.<br />
<br />
Here are two examples to illustrate the condition under which overlap is permitted.<br />
<haskell><br />
type instance F (a, Int) = [a]<br />
type instance F (Int, b) = [b] -- overlap permitted<br />
<br />
type instance G (a, Int) = [a]<br />
type instance G (Char, a) = [a] -- ILLEGAL overlap, as [Char] /= [Int]<br />
</haskell><br />
<br />
==== Decidability ====<br />
<br />
In order to guarantee that type inference in the presence of type families is decidable, we need to place a number of additional restrictions on the formation of type instance declarations (c.f., Definition 5 (Relaxed Conditions) of [http://www.cse.unsw.edu.au/~chak/papers/SPCS08.html Type Checking with Open Type Functions]). Instance declarations have the general form<br />
<haskell><br />
type instance F t1 .. tn = t<br />
</haskell><br />
where we require that for every type family application <hask>(G s1 .. sm)</hask> in <hask>t</hask>, <br />
# <hask>s1 .. sm</hask> do not contain any type family constructors,<br />
# the total number of symbols (data type constructors and type variables) in <hask>s1 .. sm</hask> is strictly smaller than in <hask>t1 .. tn</hask>, and<br />
# for every type variable <hask>a</hask>, <hask>a</hask> occurs in <hask>s1 .. sm</hask> at most as often as in <hask>t1 .. tn</hask>.<br />
These restrictions are easily verified and ensure termination of type inference. However, they are not sufficient to guarantee completeness of type inference in the presence of, so called, ''loopy equalities'', such as <hask>a ~ [F a]</hask>, where a recursive occurrence of a type variable is underneath a family application and data constructor application - see the above mentioned paper for details. <br />
<br />
If the option <tt>-XUndecidableInstances</tt> is passed to the compiler, the above restrictions are not enforced and it is on the programmer to ensure termination of the normalisation of type families during type inference.<br />
<br />
=== Equality constraints ===<br />
<br />
Type context can include equality constraints of the form <hask>t1 ~ t2</hask>, which denote that the types <hask>t1</hask> and <hask>t2</hask> need to be the same. In the presence of type families, whether two types are equal cannot generally be decided locally. Hence, the contexts of function signatures may include equality constraints, as in the following example:<br />
<haskell><br />
sumCollects :: (Collects c1, Collects c2, Elem c1 ~ Elem c2) => c1 -> c2 -> c2<br />
</haskell><br />
where we require that the element type of <hask>c1</hask> and <hask>c2</hask> are the same. In general, the types <hask>t1</hask> and <hask>t2</hask> of an equality constraint may be arbitrary monotypes; i.e., they may not contain any quantifiers, independent of whether higher-rank types are otherwise enabled.<br />
<br />
Equality constraints can also appear in class and instance contexts. The former enable a simple translation of programs using functional dependencies into programs using family synonyms instead. The general idea is to rewrite a class declaration of the form<br />
<haskell><br />
class C a b | a -> b<br />
</haskell><br />
to<br />
<haskell><br />
class (F a ~ b) => C a b where<br />
type F a<br />
</haskell><br />
That is, we represent every functional dependency (FD) <hask>a1 .. an -> b</hask> by an FD type family <hask>F a1 .. an</hask> and a superclass context equality <hask>F a1 .. an ~ b</hask>, essentially giving a name to the functional dependency. In class instances, we define the type instances of FD families in accordance with the class head. Method signatures are not affected by that process.<br />
<br />
NB: Equalities in superclass contexts are not fully implemented in the GHC 6.10 branch.<br />
<br />
== Frequently asked questions ==<br />
<br />
=== Injectivity, type inference, and ambiguity ===<br />
<br />
A common problem is this<br />
<haskell><br />
type family F a<br />
<br />
f :: F a -> F a<br />
f = undefined<br />
<br />
g :: F Int -> F Int<br />
g x = f x<br />
</haskell><br />
The compiler complains about the definition of <tt>g</tt> saying<br />
<haskell><br />
Couldn't match expected type `F Int' against inferred type `F a1'<br />
</haskell><br />
In type-checking <tt>g</tt>'s right hand side GHC discovers (by instantiating <tt>f</tt>'s type with a fresh type variable) that it has type <tt>F a1 -> F a1</tt> for some as-yet-unknown type <tt>a1</tt>. Now it tries to make the inferred type match <tt>g</tt>'s type signature. Well, you say, just make <tt>a1</tt> equal to <tt>Int</tt> and you are done. True, but what if there were these instances<br />
<haskell><br />
type instance F Int = Bool<br />
type instance F Char = Bool<br />
</haskell><br />
Then making <tt>a1</tt> equal to <tt>Char</tt> would ''also'' make the two types equal. Because there is (potentially) more than one choice, the program is rejected.<br />
<br />
However (and confusingly) if you omit the type signature on <tt>g</tt> altogether, thus<br />
<haskell><br />
f :: F a -> F a<br />
f = undefined<br />
<br />
g x = f x<br />
</haskell><br />
GHC will happily infer the type <tt>g :: F a -> F a</tt>. But you can't ''write'' that type signature (or, indeed, the more specific one above).<br />
<br />
Or, to put it another way, knowing that <tt>F t1</tt>=<tt>F t2</tt> does ''not'' imply that <tt>t1</tt> = <tt>t2</tt>.<br />
The difficulty is that the type function <tt>F</tt> need not be ''injective''; it can map two distinct types to the same type. For an injective type constructor like <tt>Maybe</tt>, if we know that <tt>Maybe t1</tt> = <tt>Maybe t2</tt>, then we know that <tt>t1</tt> = <tt>t2</tt>. But not so for non-injective type functions.<br />
<br />
'''What is the problem?''' The problem starts with <tt>f</tt>. Its type is ''ambiguous''; even if I know the argument and result types for <tt>f</tt>, I cannot use that to find the type at which <tt>a</tt> should be instantiated. (So arguably, <tt>f</tt> should be rejected as having an ambiguous type, and probably will be in future.) The situation is well known in type classes: <br />
<haskell><br />
bad :: (Read a, Show a) => String -> String<br />
bad x = show (read x)<br />
</haskell><br />
At a call of <tt>bad</tt> one cannot tell at what type <tt>a</tt> should be instantiated.<br />
<br />
The only solution is to avoid ambiguous types. In the type signature of a function, <br />
* Ensure that every type variable occurs in the part after the "<tt>=></tt>"<br />
* Ensure that every type variable appears at least once outside a type function call.<br />
Alternatively, you can use data families, which create new types and are therefore injective. The following code works:<br />
<br />
<haskell>data family F a<br />
<br />
f :: F a -> F a<br />
f = undefined<br />
<br />
g :: F Int -> F Int<br />
g x = f x</haskell><br />
<br />
== References ==<br />
<br />
* [http://www.cse.unsw.edu.au/~chak/papers/CKPM05.html Associated Types with Class.] Manuel M. T. Chakravarty, Gabriele Keller, Simon Peyton Jones, and Simon Marlow. In ''Proceedings of The 32nd Annual ACM SIGPLAN-SIGACT Symposium on Principles of Programming Languages (POPL'05)'', pages 1-13, ACM Press, 2005.<br />
* [http://www.cse.unsw.edu.au/~chak/papers/CKP05.html Associated Type Synonyms.] 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 />
* [http://www.cse.unsw.edu.au/~chak/papers/SCPD07.html System F with Type Equality Coercions.] Martin Sulzmann, Manuel M. T. Chakravarty, Simon Peyton Jones, and Kevin Donnelly. In ''Proceedings of The Third ACM SIGPLAN Workshop on Types in Language Design and Implementation'', ACM Press, 2007.<br />
* [http://www.cse.unsw.edu.au/~chak/papers/SPCS08.html Type Checking With Open Type Functions.] Tom Schrijvers, Simon Peyton-Jones, Manuel M. T. Chakravarty, Martin Sulzmann. In ''Proceedings of The 13th ACM SIGPLAN International Conference on Functional Programming'', ACM Press, pages 51-62, 2008.<br />
* [[Simonpj/Talk:FunWithTypeFuns | Fun with Type Functions]] Oleg Kiselyov, Simon Peyton Jones, Chung-chieh Shan (the source for this paper can be found at http://patch-tag.com/r/schoenfinkel/typefunctions/wiki ) <br />
<br />
[[Category:Type-level programming]]<br />
[[Category:Language extensions]]<br />
[[Category:GHC|Indexed types]]</div>Simonpjhttps://wiki.haskell.org/index.php?title=GHC/Type_families&diff=40685GHC/Type families2011-06-29T12:52:38Z<p>Simonpj: /* Injectivity, type inference, and ambiguity */</p>
<hr />
<div>Indexed type families, or '''type families''' for short, are a Haskell extension supporting ad-hoc overloading of data types. Type families are parametric types that can be assigned specialized representations based on the type parameters they are instantiated with. They are the data type analogue of [[Type class|type classes]]: families are used to define overloaded ''data'' in the same way that classes are used to define overloaded ''functions''. Type families are useful for generic programming, for creating highly parameterised library interfaces, and for creating interfaces with enhanced static information, much like dependent types.<br />
<br />
Type families come in two flavors: ''data families'' and ''type synonym families''. Data families are the indexed form of data and newtype definitions. Type synonym families are the indexed form of type synonyms. Each of these flavors can be defined in a standalone manner or ''associated'' with a type class. Standalone definitions are more general, while associated types can more clearly express how a type is used and lead to better error messages.<br />
<br />
''NB: see also Simon's [http://hackage.haskell.org/trac/ghc/blog/LetGeneralisationInGhc7 blog entry on let generalisation] for a significant change in the policy for let generalisation, driven by the type family extension. In brief: a few programs will puzzlingly fail to compile with <tt>-XTypeFamilies</tt> even though the code is legal Haskell 98.''<br />
<br />
== What are type families? ==<br />
<br />
The concept of a type family comes from type theory. An indexed type family in type theory is a partial function at the type level. Applying the function to parameters (called ''type indices'') yields a type. Type families permit a program to compute what data constructors it will operate on, rather than having them fixed statically (as with simple type systems) or treated as opaque unknowns (as with parametrically polymorphic types).<br />
<br />
Type families are to vanilla data types what type class methods are to regular functions. Vanilla polymorphic data types and functions have a single definition, which is used at all type instances. Classes and type families, on the other hand, have an interface definition and any number of instance definitions. A type family's interface definition declares its [[kind]] and its arity, or the number of type indices it takes. Instance definitions define the type family over some part of the domain.<br />
<br />
As a simple example of how type families differ from ordinary parametric data types, consider a strict list type. We can represent a list of <hask>Char</hask> in the usual way, with cons cells. We can do the same thing to represent a list of <hask>()</hask>, but since a strict <hask>()</hask> value carries no useful information, it would be more efficient to just store the length of the list. This can't be done with an ordinary parametric data type, because the data constructors used to represent the list would depend on the list's type parameter: if it's <hask>Char</hask> then the list consists of cons cells; if it's <hask>()</hask>, then the list consists of a single integer. We basically want to select between two different data types based on a type parameter. Using type families, this list type could be declared as follows:<br />
<br />
<haskell><br />
-- Declare a list-like data family<br />
data family XList a<br />
<br />
-- Declare a list-like instance for Char<br />
data instance XList Char = XCons !Char !(XList Char) | XNil<br />
<br />
-- Declare a number-like instance for ()<br />
data instance XList () = XListUnit !Int<br />
</haskell><br />
<br />
The right-hand sides of the two <code>data instance</code> declarations are exactly ordinary data definitions. However, they define two instances of the same parametric data type, <hask>XList Char</hask> and <hask>XList ()</hask>, whereas ordinary data declarations define completely unrelated types. A recent [[Simonpj/Talk:FunWithTypeFuns|tutorial paper]] has more in-depth examples of programming with type families. <br />
<br />
GADTs bear some similarity to type families, in the sense that they allow a parametric type's constructors to depend on the type's parameters. However, all GADT constructors must be defined in one place, whereas type families can be extended. Functional dependences are similar to type families, and many type classes that use functional dependences can be equivalently expressed with type families. Type families provide a more functional style of type-level programming than the relational style of functional dependences.<br />
<br />
== What do I need to use type families? ==<br />
<br />
Type families are a GHC extension enabled with the <code>-XTypeFamilies</code> flag or the <code>{-# LANGUAGE TypeFamilies #-}</code> pragma. The first stable release of GHC that properly supports type families is 6.10.1. (The 6.8 release included an early partial implementation, but its use is deprecated.) Please [http://hackage.haskell.org/trac/ghc/query?status=new&status=assigned&status=reopened&group=priority&type=bug&order=id&desc=1 report bugs] via the GHC bug tracker, ideally accompanied by a small example program that demonstrates the problem. Use the [mailto:glasgow-haskell-users@haskell.org GHC mailing list] for questions or for a discussion of this language extension and its description on this wiki page.<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-families.html#data-family-declarations ''kind signature''] (here <hask>* -> *</hask>) for the associated data type <hask>GMap k</hask> - analogous 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.IntMap</hask>, thusly:<br />
<haskell><br />
instance GMapKey Int where<br />
data GMap Int v = GMapInt (Data.IntMap.IntMap v)<br />
empty = GMapInt Data.IntMap.empty<br />
lookup k (GMapInt m) = Data.IntMap.lookup k m<br />
insert k v (GMapInt m) = GMapInt (Data.IntMap.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 fundamental 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 />
Next, 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 b) v (GMapEither gm1 gm2) = GMapEither gm1 (insert b v gm2)<br />
</haskell><br />
If you find this code algorithmically surprising, I'd suggest to have a look at [http://www.cs.ox.ac.uk/ralf.hinze/publications/index.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 querying 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 source code[http://darcs.haskell.org/testsuite/tests/ghc-regress/indexed-types/should_run/GMapAssoc.hs] for <hask>GMap</hask> from GHC's test suite.<br />
<br />
== Detailed definition of data families ==<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-indices to coincide with the class parameters. However, the latter 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> keyword. 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-indices. 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. In other words: '''the named type parameters of the data declaration must be a permutation of a subset of the class variables'''. <br />
<br />
Example is admissible:<br />
<haskell><br />
class C a b c where { data T c a :: * } -- OK<br />
class C a b c where { data T a a :: * } -- Bad: repeated variable<br />
class D a where { data T a x :: * } -- Bad: x is not a class variable<br />
class D a where { data T a :: * -> * } -- OK<br />
</haskell><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, but may not contain forall types or type synonym families. However, data families are generally allowed in type parameters, and type synonyms are allowed as long as they are fully applied and expand to a type that is itself admissible - exactly as this is required for occurrences of type synonyms in class instance parameters. 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 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 />
nonsense :: T a -> Int<br />
nonsense A = 1 -- WRONG: These two equations together...<br />
nonsense 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 - 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 indices corresponding to class parameters must be identical to the type given in the instance head; here this is the 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 instance 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 />
==== Scoping of class parameters ====<br />
<br />
In the case of multi-parameter type classes, the visibility of class parameters in the right-hand side of associated family instances depends ''solely'' on the parameters of the data family. As an example, consider the simple class declaration<br />
<haskell><br />
class C a b where<br />
data T a<br />
</haskell><br />
Only one of the two class parameters is a parameter to the data family. Hence, the following instance declaration is invalid:<br />
<haskell><br />
instance C [c] d where<br />
data T [c] = MkT (c, d) -- WRONG!! 'd' is not in scope<br />
</haskell><br />
Here, the right-hand side of the data instance mentions the type variable <hask>d</hask> that does not occur in its left-hand side. We cannot admit such data instances as they would compromise type safety.<br />
<br />
==== Type class instances of family 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 implicitly 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 is 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>GMapEither</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 />
== An associated type synonym example ==<br />
<br />
Type synonym families are an alternative to functional dependencies, which makes functional dependency examples well suited to introduce type synonym families. In fact, type families are a more functional way to express the same as functional dependencies (despite the name!), as they replace the relational notation of functional dependencies by an expression-oriented notation; i.e., functions on types are really represented by functions and not relations.<br />
<br />
=== The <hask>class</hask> declaration ===<br />
<br />
Here's an example from Mark Jones' seminal paper on functional dependencies:<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 />
Instead of the multi-parameter type class, we use a single parameter class, and the parameter <hask>e</hask><br />
turned into an associated type synonym <hask>Elem ce</hask>.<br />
<br />
=== An <hask>instance</hask>===<br />
<br />
Instances change correspondingly. An instance of the two-parameter class<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) <br />
| e == x = True<br />
| otherwise = member e xs<br />
toList l = l<br />
</haskell><br />
becomes an instance of a single-parameter class, where the dependent type parameter turns into an associated type instance declaration:<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) <br />
| 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 />
== Detailed definition of type synonym families ==<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-indices to coincide with the class parameters. However, the latter 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 />
Parameters can also be given explicit kind signatures if needed. We call the number of parameters in a type family declaration, the family's arity, and all applications of a type family must be fully saturated w.r.t. to that arity. This requirement is unlike ordinary type synonyms and it implies that the kind of a type family is not sufficient to determine a family's arity, and hence in general, also insufficient to determine whether a type family application is well formed. As an example, consider the following declaration:<br />
<haskell><br />
type family F a b :: * -> * -- F's arity is 2, <br />
-- although its overall kind is * -> * -> * -> *<br />
</haskell><br />
Given this declaration the following are examples of well-formed and malformed types:<br />
<haskell><br />
F Char [Int] -- OK! Kind: * -> *<br />
F Char [Int] Bool -- OK! Kind: *<br />
F IO Bool -- WRONG: kind mismatch in the first argument<br />
F Bool -- WRONG: unsaturated application<br />
</haskell><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 />
Exactly as in the case of an associated data declaration, '''the named type parameters must be a permutation of a subset of the class parameters'''. Examples<br />
<haskell><br />
class C a b c where { type T c a :: * } -- OK<br />
class D a where { type T a x :: * } -- No: x is not a class parameter<br />
class D a where { type T a :: * -> * } -- OK<br />
</haskell><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, but may not contain forall types or type synonym families. However, data families are generally allowed, and type synonyms are allowed as long as they are fully applied and expand to a type that is admissible - these are the exact same requirements as for data instances. For example, the <hask>[e]</hask> instance for <hask>Elem</hask> is<br />
<haskell><br />
type instance Elem [e] = e<br />
</haskell><br />
<br />
A type family instance declaration must satisfy the following rules:<br />
* An appropriate family declaration is in scope - just like class instances require the class declaration to be visible. <br />
* The instance declaration conforms to the kind determined by its family declaration<br />
* The number of type parameters in an instance declaration matches the number of type parameters in the family declaration.<br />
* The right-hand side of a type instance must be a monotype (i.e., it may not include foralls) and after the expansion of all saturated vanilla type synonyms, no synonyms, except family synonyms may remain.<br />
<br />
Here are some examples of admissible and illegal type instances:<br />
<haskell><br />
type family F a :: *<br />
type instance F [Int] = Int -- OK!<br />
type instance F String = Char -- OK!<br />
type instance F (F a) = a -- WRONG: type parameter mentions a type family<br />
type instance F (forall a. (a, b)) = b -- WRONG: a forall type appears in a type parameter<br />
type instance F Float = forall a.a -- WRONG: right-hand side may not be a forall type<br />
<br />
type family G a b :: * -> *<br />
type instance G Int = (,) -- WRONG: must be two type parameters<br />
type instance G Int Char Float = Double -- WRONG: must be two type parameters<br />
</haskell><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 instance 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 only overlap if the right-hand sides of the overlapping instances coincide for the overlapping types. More formally, two instance declarations overlap if there is a substitution that makes the left-hand sides of the instances syntactically the same. Whenever that is the case, the right-hand sides of the instances must also be syntactically equal under the same substitution. This condition is independent of whether the type family is associated or not, and it is not only a matter of consistency, but one of type safety.<br />
<br />
Here are two examples to illustrate the condition under which overlap is permitted.<br />
<haskell><br />
type instance F (a, Int) = [a]<br />
type instance F (Int, b) = [b] -- overlap permitted<br />
<br />
type instance G (a, Int) = [a]<br />
type instance G (Char, a) = [a] -- ILLEGAL overlap, as [Char] /= [Int]<br />
</haskell><br />
<br />
==== Decidability ====<br />
<br />
In order to guarantee that type inference in the presence of type families is decidable, we need to place a number of additional restrictions on the formation of type instance declarations (c.f., Definition 5 (Relaxed Conditions) of [http://www.cse.unsw.edu.au/~chak/papers/SPCS08.html Type Checking with Open Type Functions]). Instance declarations have the general form<br />
<haskell><br />
type instance F t1 .. tn = t<br />
</haskell><br />
where we require that for every type family application <hask>(G s1 .. sm)</hask> in <hask>t</hask>, <br />
# <hask>s1 .. sm</hask> do not contain any type family constructors,<br />
# the total number of symbols (data type constructors and type variables) in <hask>s1 .. sm</hask> is strictly smaller than in <hask>t1 .. tn</hask>, and<br />
# for every type variable <hask>a</hask>, <hask>a</hask> occurs in <hask>s1 .. sm</hask> at most as often as in <hask>t1 .. tn</hask>.<br />
These restrictions are easily verified and ensure termination of type inference. However, they are not sufficient to guarantee completeness of type inference in the presence of, so called, ''loopy equalities'', such as <hask>a ~ [F a]</hask>, where a recursive occurrence of a type variable is underneath a family application and data constructor application - see the above mentioned paper for details. <br />
<br />
If the option <tt>-XUndecidableInstances</tt> is passed to the compiler, the above restrictions are not enforced and it is on the programmer to ensure termination of the normalisation of type families during type inference.<br />
<br />
=== Equality constraints ===<br />
<br />
Type context can include equality constraints of the form <hask>t1 ~ t2</hask>, which denote that the types <hask>t1</hask> and <hask>t2</hask> need to be the same. In the presence of type families, whether two types are equal cannot generally be decided locally. Hence, the contexts of function signatures may include equality constraints, as in the following example:<br />
<haskell><br />
sumCollects :: (Collects c1, Collects c2, Elem c1 ~ Elem c2) => c1 -> c2 -> c2<br />
</haskell><br />
where we require that the element type of <hask>c1</hask> and <hask>c2</hask> are the same. In general, the types <hask>t1</hask> and <hask>t2</hask> of an equality constraint may be arbitrary monotypes; i.e., they may not contain any quantifiers, independent of whether higher-rank types are otherwise enabled.<br />
<br />
Equality constraints can also appear in class and instance contexts. The former enable a simple translation of programs using functional dependencies into programs using family synonyms instead. The general idea is to rewrite a class declaration of the form<br />
<haskell><br />
class C a b | a -> b<br />
</haskell><br />
to<br />
<haskell><br />
class (F a ~ b) => C a b where<br />
type F a<br />
</haskell><br />
That is, we represent every functional dependency (FD) <hask>a1 .. an -> b</hask> by an FD type family <hask>F a1 .. an</hask> and a superclass context equality <hask>F a1 .. an ~ b</hask>, essentially giving a name to the functional dependency. In class instances, we define the type instances of FD families in accordance with the class head. Method signatures are not affected by that process.<br />
<br />
NB: Equalities in superclass contexts are not fully implemented in the GHC 6.10 branch.<br />
<br />
== Frequently asked questions ==<br />
<br />
=== Injectivity, type inference, and ambiguity ===<br />
<br />
A common problem is this<br />
<haskell><br />
type family F a<br />
<br />
f :: F a -> F a<br />
f = undefined<br />
<br />
g :: F Int -> F Int<br />
g x = f x<br />
</haskell><br />
The compiler complains about the definition of <tt>g</tt> saying<br />
<haskell><br />
Couldn't match expected type `F Int' against inferred type `F a1'<br />
</haskell><br />
In type-checking <tt>g</tt>'s right hand side GHC discovers (by instantiating <tt>f</tt>'s type with a fresh type variable) that it has type <tt>F a1 -> F a1</tt> for some as-yet-unknown type <tt>a1</tt>. Now it tries to make the inferred type match <tt>g</tt>'s type signature. Well, you say, just make <tt>a1</tt> equal to <tt>Int</tt> and you are done. True, but what if there were these instances<br />
<haskell><br />
type instance F Int = Bool<br />
type instance F Char = Bool<br />
</haskell><br />
Then making <tt>a1</tt> equal to <tt>Char</tt> would ''also'' make the two types equal. Because there is (potentially) more than one choice, the program is rejected.<br />
<br />
However (and confusingly) if you omit the type signature on <tt>g</tt> altogether, GHC will happily infer the type <tt>g :: F a -> F a</tt>. But you can't ''write'' that type signature (or, indeed, the more specific one above).<br />
<br />
Or, to put it another way, knowing that <tt>F t1</tt>=<tt>F t2</tt> does ''not'' imply that <tt>t1</tt> = <tt>t2</tt>.<br />
The difficulty is that the type function <tt>F</tt> need not be ''injective''; it can map two distinct types to the same type. For an injective type constructor like <tt>Maybe</tt>, if we know that <tt>Maybe t1</tt> = <tt>Maybe t2</tt>, then we know that <tt>t1</tt> = <tt>t2</tt>. But not so for non-injective type functions.<br />
<br />
The problem starts with <tt>f</tt>. Its type is ''ambiguous''; even if I know the argument and result types for <tt>f</tt>, I cannot use that to find the type at which <tt>a</tt> should be instantiated. (So arguably, <tt>f</tt> should be rejected as having an ambiguous type, and probably will be in future.) The situation is well known in type classes: <br />
<haskell><br />
bad :: (Read a, Show a) => String -> String<br />
bad x = show (read x)<br />
</haskell><br />
At a call of <tt>bad</tt> one cannot tell at what type <tt>a</tt> should be instantiated.<br />
<br />
The only solution is to avoid ambiguous types. In the type signature of a function, <br />
* Ensure that every type variable occurs in the part after the "<tt>=></tt>"<br />
* Ensure that every type variable appears at least once outside a type function call.<br />
Alternatively, you can use data families, which create new types and are therefore injective. The following code works:<br />
<br />
<haskell>data family F a<br />
<br />
f :: F a -> F a<br />
f = undefined<br />
<br />
g :: F Int -> F Int<br />
g x = f x</haskell><br />
<br />
== References ==<br />
<br />
* [http://www.cse.unsw.edu.au/~chak/papers/CKPM05.html Associated Types with Class.] Manuel M. T. Chakravarty, Gabriele Keller, Simon Peyton Jones, and Simon Marlow. In ''Proceedings of The 32nd Annual ACM SIGPLAN-SIGACT Symposium on Principles of Programming Languages (POPL'05)'', pages 1-13, ACM Press, 2005.<br />
* [http://www.cse.unsw.edu.au/~chak/papers/CKP05.html Associated Type Synonyms.] 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 />
* [http://www.cse.unsw.edu.au/~chak/papers/SCPD07.html System F with Type Equality Coercions.] Martin Sulzmann, Manuel M. T. Chakravarty, Simon Peyton Jones, and Kevin Donnelly. In ''Proceedings of The Third ACM SIGPLAN Workshop on Types in Language Design and Implementation'', ACM Press, 2007.<br />
* [http://www.cse.unsw.edu.au/~chak/papers/SPCS08.html Type Checking With Open Type Functions.] Tom Schrijvers, Simon Peyton-Jones, Manuel M. T. Chakravarty, Martin Sulzmann. In ''Proceedings of The 13th ACM SIGPLAN International Conference on Functional Programming'', ACM Press, pages 51-62, 2008.<br />
* [[Simonpj/Talk:FunWithTypeFuns | Fun with Type Functions]] Oleg Kiselyov, Simon Peyton Jones, Chung-chieh Shan (the source for this paper can be found at http://patch-tag.com/r/schoenfinkel/typefunctions/wiki ) <br />
<br />
[[Category:Type-level programming]]<br />
[[Category:Language extensions]]<br />
[[Category:GHC|Indexed types]]</div>Simonpjhttps://wiki.haskell.org/index.php?title=Library_submissions/NewDraft&diff=40485Library submissions/NewDraft2011-06-10T07:37:15Z<p>Simonpj: Replacing page with 'See Library_submissions'</p>
<hr />
<div>See [[Library_submissions]]</div>Simonpjhttps://wiki.haskell.org/index.php?title=Library_submissions&diff=40484Library submissions2011-06-10T07:36:35Z<p>Simonpj: /* The Core Libraries */</p>
<hr />
<div>This page describes the process for maintaining the <br />
'''Core libraries'''. The core libraries are a subset of the packages in the<br />
Haskell Platform, and define basic APIs that are expected to be<br />
available in any Haskell implementation. They are listed under "The Core Libraries" below.<br />
<br />
Non-core libraries are, of course, managed by their own authors/maintainers (named in their .cabal file), using whatever policies those maintainers see fit. [Note: arguably the policies below might usefully be applied to all libraries embodied in the Haskell Platform, but that is a question for the HP team.]<br />
<br />
= General principles =<br />
<br />
* Each core package has a named maintainer, or small group of maintainers, who have commit access to the package. <br />
<br />
* Third parties are encouraged to make proposals for changes, both to the library API and its implementation, by sending the proposal to the maintainer (CC'ing the libraries mailing list).<br />
<br />
* The maintainer is trusted to decide what changes to make to the package, and when. They are strongly encouraged to follow the guidance below, but the general principle is: the community offers opinions, but the maintainers decide.<br />
<br />
<br />
= Responsiveness =<br />
<br />
* Third parties submitting proposals to the maintainer of a library can expect a timely and thoughtful response. <br />
* The more effort the proposer invests (for example, by constructing a patch rather than making an off-the-cuff suggestion) the more consideration s/he can reasonably expect.<br />
* Proposals that have widespread support, and are accompanied by patches (preferably with tests and documentation), should normally be accepted by the maintainer. <br />
* It is up to the maintainer to decide what "widespread" means; in particular, it does not always mean "a majority of those who responded". The majority-responder story is vulnerable to selection bias; e.g. 7 people (out of a client base of hundreds) say "add this function" but the maintainer thinks it will make the interface incrementally more complicated without sufficient benefit.<br />
* Where there is significant work involved in implementing a proposal, it is reasonable for a maintainer to ask for a patch. The principle is that maintainers are not obliged to do the work of implementing a proposal, even if it does enjoy wide support. For more substantial changes, it makes sense to develop the implementation in dialogue with the maintainer.<br />
<br />
= Guidance for proposers =<br />
<br />
A "proposal" can be anything from a one-sentence suggestion to a fully-implemented, tested, and documented patch.<br />
However, the more substantial the proposal the more attention you can expect. The process is this:<br />
<br />
* Send your proposal by email to the maintainer, with a copy to the libraries@haskell.org mailing list (which you need to [http://www.haskell.org/mailman/listinfo/libraries subscribe] to before posting).<br />
<br />
* Set a deadline for discussion (no less than two weeks), and act as chair/moderator for the discussion. <br />
<br />
* At the end of the discussion period, summarise your understanding of the consensus (or lack thereof), including a link to the thread in the mailing list archives, and send the summary to the maintainer for decision. The deadline gives you a moment to summarise the debate and hand over to the maintainer. It isn't a deadline for the maintainer to decide; for example he or she may seek more discussion first. <br />
<br />
* If the decision is positive, [http://hackage.haskell.org/trac/ghc/newticket create a ticket] on the GHC trac. The description of the ticket can summarise the proposal and link to the mail thread. Further discussion and implementation patches can be attached to the ticket, and the ticket helps the maintainer to keep track of what is on the go. (Obviously if the maintainer prefers some other mechanism, follow his or her guidance.)<br />
<br />
* For non-trivial changes the maintainer may ask for a patch. You may create the patch up front, and make it part of your proposal; or you may want to have some discussion about the design first, and only then roll up your sleeves to do the implementation; and for bigger jobs you may want to wait until the maintainer agrees in principle with the change.<br />
<br />
Here are desirable properties for a proposal and its implementation. The more of these properties your proposal or patch has, the more likely it is that the maintainer will adopt your idea. After all, to adopt it the maintainter will have to do whatever tasks you didn't do.<br />
<br />
* '''Description'''. A good proposal says clearly ''what'' you propose, ''why'' it is a good idea, and what its consequences would be.<br />
* '''Patch'''. Use <tt>darcs record</tt> or <tt>git commit</tt> (depending on what sort of repo the library lives in) to create it. Save the patch to a file, using <tt>darcs send --output</tt> or <tt>git format-patch</tt>. Make your changes against a copy of the master branch of the relevant library, and make sure it compiles.<br />
* '''Portability'''. Good code is portable. In particular, try to ensure the code runs in Hugs and GHC, and on Windows and Linux.<br />
* '''Style'''. Good code follows the conventions in the library you are modifying.<br />
* '''Documentation'''. Good code includes valid [http://haskell.org/haddock Haddock] documentation.<br />
* '''Tests'''. Good patches have suitable tests for the library's testsuite.<br />
<br />
= Guidance for maintainers =<br />
<br />
The principle is that we '''trust the maintainer''' to behave sensibly. The guidelines below are just that: guidelines, not rules. Still, the core libraries are used by many, many people, so maintainers should make every effort not to mess them up by accident. <br />
<br />
* '''API changes should be discussed''' on the libraries mailing list prior to making the change, even if the maintainer is the proposer. The maintainer still has ultimate say in what changes are made, but the community should have the opportunity to comment on changes. However, unaminity (or even a majority) is not required.<br />
<br />
* '''Every API change should be described precisely in the commit log.''' The commit logs should be sent to a public mailing list, or otherwise made easily available (e.g. via github), so that the community can keep an eye on changes and comment.<br />
<br />
* '''Backwards compatibility''' is important to many users. API changes are expected to retain backwards compatibility wherever possible. However, from time to time we may decide to have major revisions which are explicitly not backwards compatible; in these cases we may try to make the previous version of the package available concurrently, as in the base-3/base-4 switchover.<br />
<br />
* You don't need to consult the community for '''purely internal changes'''; i.e. changes that do not affect the library's clients.<br />
<br />
* Changes that simply '''widen the API by adding new functions''' are a bit of a grey area. It's better to consult the community, becuase there may be useful feedback about (say) the order of arguments, or the name of the function, or whatnot. On the other hand few clients will actually break if you add a new function to the API. Use your judgement.<br />
<br />
Libraries maintained by the GHC team are subject to the GHC validation policy - patches will be tested for validation before committing. Those packages not maintained by the GHC team will probably have a GHC lagging mirror repository that is subject to validation.<br />
<br />
= The Core Libraries =<br />
<br />
The following packages constitute the core libraries:<br />
<br />
{| border="1"<br />
! Package !! Maintainer<br />
|-<br />
| [http://hackage.haskell.org/package/array array] || GHC HQ<br />
|-<br />
| [http://hackage.haskell.org/package/base base] || GHC HQ<br />
|-<br />
| [http://hackage.haskell.org/package/containers containers] || Johan Tibell and Milan Straka<br />
|-<br />
| [http://hackage.haskell.org/package/directory directory] || GHC HQ<br />
|-<br />
| [http://hackage.haskell.org/package/mtl mtl] || Edward Kmett<br />
|-<br />
| [http://hackage.haskell.org/package/pretty pretty] || David Terei<br />
|-<br />
| [http://hackage.haskell.org/package/process process] || GHC HQ <br />
|-<br />
| [http://hackage.haskell.org/package/random random] || Chris Dornan and Ryan Newton<br />
|-<br />
| [http://hackage.haskell.org/package/unix unix] || GHC HQ<br />
|-<br />
|-<br />
| [http://hackage.haskell.org/package/template-haskell template-haskell] || GHC HQ<br />
|-<br />
| [http://hackage.haskell.org/package/parallel parallel] || Simon Marlow<br />
|-<br />
| [http://hackage.haskell.org/package/hpc hpc] || Andy Gill <br />
|-<br />
| [http://hackage.haskell.org/package/ghc-prim ghc-prim] || GHC HQ <br />
|-<br />
| [http://hackage.haskell.org/package/extensible-exceptions extensible-exceptions] || GHC HQ <br />
|-<br />
| [http://hackage.haskell.org/package/deepseq deepseq] || Simon Marlow<br />
|-<br />
| [http://hackage.haskell.org/package/Win32 Win32] || Volunteer needed <br />
|}<br />
<br />
* The maintainer "GHC HQ" means Simon Marlow, Simon Peyton Jones, and Ian Lynagh. Email cvs-ghc@haskell.org<br />
* "Volunteer needed" means that GHC HQ is the default maintainer, but that we'd like someone else to volunteer please!<br />
<br />
The following packages match the appropriate language standard, and as such cannot change independently. The code is maintained by the GHC team.<br />
<br />
{| border="1"<br />
|-<br />
| [http://hackage.haskell.org/package/haskell2010 haskell2010] || GHC HQ<br />
|-<br />
| [http://hackage.haskell.org/package/haskell98 haskell98] || GHC HQ<br />
|}<br />
<br />
These packages are maintained only for backward compatibility, and are not expected to undergo API changes in the future. <br />
<br />
{| border="1"<br />
|-<br />
| [http://hackage.haskell.org/package/old-locale old-locale] || GHC HQ <br />
|-<br />
| [http://hackage.haskell.org/package/old-time old-time] || GHC HQ <br />
|}<br />
<br />
= See also =<br />
<br />
* [http://hackage.haskell.org/trac/ghc/wiki/WorkingConventions GHC Working Conventions], including guidelines for submitting patches via darcs.<br />
* [http://haskell.org/haskellwiki/Category:Style Notes on programming style]<br />
<br />
[[Category:Community]]<br />
[[Category:Proposals| ]]</div>Simonpjhttps://wiki.haskell.org/index.php?title=Library_submissions&diff=40483Library submissions2011-06-10T07:35:46Z<p>Simonpj: </p>
<hr />
<div>This page describes the process for maintaining the <br />
'''Core libraries'''. The core libraries are a subset of the packages in the<br />
Haskell Platform, and define basic APIs that are expected to be<br />
available in any Haskell implementation. They are listed under "The Core Libraries" below.<br />
<br />
Non-core libraries are, of course, managed by their own authors/maintainers (named in their .cabal file), using whatever policies those maintainers see fit. [Note: arguably the policies below might usefully be applied to all libraries embodied in the Haskell Platform, but that is a question for the HP team.]<br />
<br />
= General principles =<br />
<br />
* Each core package has a named maintainer, or small group of maintainers, who have commit access to the package. <br />
<br />
* Third parties are encouraged to make proposals for changes, both to the library API and its implementation, by sending the proposal to the maintainer (CC'ing the libraries mailing list).<br />
<br />
* The maintainer is trusted to decide what changes to make to the package, and when. They are strongly encouraged to follow the guidance below, but the general principle is: the community offers opinions, but the maintainers decide.<br />
<br />
<br />
= Responsiveness =<br />
<br />
* Third parties submitting proposals to the maintainer of a library can expect a timely and thoughtful response. <br />
* The more effort the proposer invests (for example, by constructing a patch rather than making an off-the-cuff suggestion) the more consideration s/he can reasonably expect.<br />
* Proposals that have widespread support, and are accompanied by patches (preferably with tests and documentation), should normally be accepted by the maintainer. <br />
* It is up to the maintainer to decide what "widespread" means; in particular, it does not always mean "a majority of those who responded". The majority-responder story is vulnerable to selection bias; e.g. 7 people (out of a client base of hundreds) say "add this function" but the maintainer thinks it will make the interface incrementally more complicated without sufficient benefit.<br />
* Where there is significant work involved in implementing a proposal, it is reasonable for a maintainer to ask for a patch. The principle is that maintainers are not obliged to do the work of implementing a proposal, even if it does enjoy wide support. For more substantial changes, it makes sense to develop the implementation in dialogue with the maintainer.<br />
<br />
= Guidance for proposers =<br />
<br />
A "proposal" can be anything from a one-sentence suggestion to a fully-implemented, tested, and documented patch.<br />
However, the more substantial the proposal the more attention you can expect. The process is this:<br />
<br />
* Send your proposal by email to the maintainer, with a copy to the libraries@haskell.org mailing list (which you need to [http://www.haskell.org/mailman/listinfo/libraries subscribe] to before posting).<br />
<br />
* Set a deadline for discussion (no less than two weeks), and act as chair/moderator for the discussion. <br />
<br />
* At the end of the discussion period, summarise your understanding of the consensus (or lack thereof), including a link to the thread in the mailing list archives, and send the summary to the maintainer for decision. The deadline gives you a moment to summarise the debate and hand over to the maintainer. It isn't a deadline for the maintainer to decide; for example he or she may seek more discussion first. <br />
<br />
* If the decision is positive, [http://hackage.haskell.org/trac/ghc/newticket create a ticket] on the GHC trac. The description of the ticket can summarise the proposal and link to the mail thread. Further discussion and implementation patches can be attached to the ticket, and the ticket helps the maintainer to keep track of what is on the go. (Obviously if the maintainer prefers some other mechanism, follow his or her guidance.)<br />
<br />
* For non-trivial changes the maintainer may ask for a patch. You may create the patch up front, and make it part of your proposal; or you may want to have some discussion about the design first, and only then roll up your sleeves to do the implementation; and for bigger jobs you may want to wait until the maintainer agrees in principle with the change.<br />
<br />
Here are desirable properties for a proposal and its implementation. The more of these properties your proposal or patch has, the more likely it is that the maintainer will adopt your idea. After all, to adopt it the maintainter will have to do whatever tasks you didn't do.<br />
<br />
* '''Description'''. A good proposal says clearly ''what'' you propose, ''why'' it is a good idea, and what its consequences would be.<br />
* '''Patch'''. Use <tt>darcs record</tt> or <tt>git commit</tt> (depending on what sort of repo the library lives in) to create it. Save the patch to a file, using <tt>darcs send --output</tt> or <tt>git format-patch</tt>. Make your changes against a copy of the master branch of the relevant library, and make sure it compiles.<br />
* '''Portability'''. Good code is portable. In particular, try to ensure the code runs in Hugs and GHC, and on Windows and Linux.<br />
* '''Style'''. Good code follows the conventions in the library you are modifying.<br />
* '''Documentation'''. Good code includes valid [http://haskell.org/haddock Haddock] documentation.<br />
* '''Tests'''. Good patches have suitable tests for the library's testsuite.<br />
<br />
= Guidance for maintainers =<br />
<br />
The principle is that we '''trust the maintainer''' to behave sensibly. The guidelines below are just that: guidelines, not rules. Still, the core libraries are used by many, many people, so maintainers should make every effort not to mess them up by accident. <br />
<br />
* '''API changes should be discussed''' on the libraries mailing list prior to making the change, even if the maintainer is the proposer. The maintainer still has ultimate say in what changes are made, but the community should have the opportunity to comment on changes. However, unaminity (or even a majority) is not required.<br />
<br />
* '''Every API change should be described precisely in the commit log.''' The commit logs should be sent to a public mailing list, or otherwise made easily available (e.g. via github), so that the community can keep an eye on changes and comment.<br />
<br />
* '''Backwards compatibility''' is important to many users. API changes are expected to retain backwards compatibility wherever possible. However, from time to time we may decide to have major revisions which are explicitly not backwards compatible; in these cases we may try to make the previous version of the package available concurrently, as in the base-3/base-4 switchover.<br />
<br />
* You don't need to consult the community for '''purely internal changes'''; i.e. changes that do not affect the library's clients.<br />
<br />
* Changes that simply '''widen the API by adding new functions''' are a bit of a grey area. It's better to consult the community, becuase there may be useful feedback about (say) the order of arguments, or the name of the function, or whatnot. On the other hand few clients will actually break if you add a new function to the API. Use your judgement.<br />
<br />
Libraries maintained by the GHC team are subject to the GHC validation policy - patches will be tested for validation before committing. Those packages not maintained by the GHC team will probably have a GHC lagging mirror repository that is subject to validation.<br />
<br />
= The Core Libraries =<br />
<br />
The "core libraries" are by definition the ones that (until now) have listed their maintainer as "libraries@haskell.org". The following packages constitute the core libraries:<br />
<br />
{| border="1"<br />
! Package !! Maintainer<br />
|-<br />
| [http://hackage.haskell.org/package/array array] || GHC HQ<br />
|-<br />
| [http://hackage.haskell.org/package/base base] || GHC HQ<br />
|-<br />
| [http://hackage.haskell.org/package/containers containers] || Johan Tibell and Milan Straka<br />
|-<br />
| [http://hackage.haskell.org/package/directory directory] || GHC HQ<br />
|-<br />
| [http://hackage.haskell.org/package/mtl mtl] || Edward Kmett<br />
|-<br />
| [http://hackage.haskell.org/package/pretty pretty] || David Terei<br />
|-<br />
| [http://hackage.haskell.org/package/process process] || GHC HQ <br />
|-<br />
| [http://hackage.haskell.org/package/random random] || Chris Dornan and Ryan Newton<br />
|-<br />
| [http://hackage.haskell.org/package/unix unix] || GHC HQ<br />
|-<br />
|-<br />
| [http://hackage.haskell.org/package/template-haskell template-haskell] || GHC HQ<br />
|-<br />
| [http://hackage.haskell.org/package/parallel parallel] || Simon Marlow<br />
|-<br />
| [http://hackage.haskell.org/package/hpc hpc] || Andy Gill <br />
|-<br />
| [http://hackage.haskell.org/package/ghc-prim ghc-prim] || GHC HQ <br />
|-<br />
| [http://hackage.haskell.org/package/extensible-exceptions extensible-exceptions] || GHC HQ <br />
|-<br />
| [http://hackage.haskell.org/package/deepseq deepseq] || Simon Marlow<br />
|-<br />
| [http://hackage.haskell.org/package/Win32 Win32] || Volunteer needed <br />
|}<br />
<br />
* The maintainer "GHC HQ" means Simon Marlow, Simon Peyton Jones, and Ian Lynagh. <br />
* "Volunteer needed" means that GHC HQ is the default maintainer, but that we'd like someone else to volunteer please!<br />
<br />
The following packages match the appropriate language standard, and as such cannot change independently. The code is maintained by the GHC team.<br />
<br />
{| border="1"<br />
|-<br />
| [http://hackage.haskell.org/package/haskell2010 haskell2010] || GHC HQ<br />
|-<br />
| [http://hackage.haskell.org/package/haskell98 haskell98] || GHC HQ<br />
|}<br />
<br />
These packages are maintained only for backward compatibility, and are not expected to undergo API changes in the future. <br />
<br />
{| border="1"<br />
|-<br />
| [http://hackage.haskell.org/package/old-locale old-locale] || GHC HQ <br />
|-<br />
| [http://hackage.haskell.org/package/old-time old-time] || GHC HQ <br />
|}<br />
<br />
= See also =<br />
<br />
* [http://hackage.haskell.org/trac/ghc/wiki/WorkingConventions GHC Working Conventions], including guidelines for submitting patches via darcs.<br />
* [http://haskell.org/haskellwiki/Category:Style Notes on programming style]<br />
<br />
[[Category:Community]]<br />
[[Category:Proposals| ]]</div>Simonpjhttps://wiki.haskell.org/index.php?title=Library_submissions/OldProcess&diff=40482Library submissions/OldProcess2011-06-10T07:34:18Z<p>Simonpj: /* THE OLD LIBRARY PROCESSS, NOW SUPERCEDED */</p>
<hr />
<div>= THE OLD LIBRARY PROCESSS, NOW SUPERCEDED =<br />
<br />
'''This page describes the old library process, which was superceded in June 2011. It's preserved here only for old times sake. <br />
See the new process at [[Library_submissions]]'''<br />
<br />
---------------------------------------------<br />
<br />
As the Haskell community has grown, and emphasis on development has<br />
moved from language to libraries, the need for a more formalised process<br />
for contributing to libraries has emerged. This page documents our<br />
'best practices' for proposing changes to library interfaces<br />
(e.g. new modules or functions, removing functions) in packages that list ''libraries@haskell.org'' as maintainer.<br />
We have been using it since October 2006.<br />
<br />
In essence, we don't want proposals to go unnoticed, but changes to<br />
basic interfaces also need thorough consideration. <br />
<br />
== Creating a proposal ==<br />
<br />
In order to ensure we have something concrete to discuss, please follow<br />
the following guidelines:<br />
<br />
* ''Currency''. Make your changes against a copy of the HEAD branch of the [http://hackage.haskell.org/trac/ghc/wiki/DarcsRepositories relevant library], and make sure it compiles.<br />
* ''Portability''. Code should be portable. If it is not portable, reasons should be given. At the very least ensure the code runs in Hugs and GHC, and on Windows and Linux.<br />
* ''Style''. Follow the conventions in the library you are modifying.<br />
* ''Documentation''. It must include valid [http://haskell.org/haddock Haddock] documentation.<br />
* ''Tests''. Code should ideally also come with suitable tests for the testsuite. There's currently some disagreement about what this means. Discussion of where we may want to head is in the [[library tests]] page.<br />
<br />
== Submitting the proposal ==<br />
<br />
* ''Patch''. Create a [http://darcs.net darcs] or git patch (depending on what sort of repo the library lives in) of your change using <tt>darcs record</tt> or <tt>git commit -a</tt>, including a rationale for the change. Save the patch to a file, using <tt>darcs send --output</tt> or <tt>git format-patch</tt>.<br />
<br />
* ''Submission''. Start a new thread on the libraries@haskell.org mailing list (which you need to [http://www.haskell.org/mailman/listinfo/libraries subscribe] to before posting), with a subject beginning "Proposal:". Include a description of the change and the rationale, and attach the patch. You may wish to include a pointer to updated Haddock documentation, if relevant. You must also include a deadline for the discussion period; it must allow at least 2 weeks for discussion, but you may allow more - particularly if many people are likely to be away during the next 2 weeks. If discussion is still ongoing at the deadline, the discussion period can be extended.<br />
<br />
If someone has done all this, they are entitled to expect feedback;<br />
silence during the discussion period can be interpreted as consent.<br />
<br />
== At the end of the discussion period ==<br />
<br />
* Determine whether consensus for the change was reached. A deeply held disagreement at this point may require some form of governance (voting, dictatorship, etc). This should be a rare event.<br />
<br />
* If consensus was achieved, file a [http://hackage.haskell.org/trac/ghc/newticket ticket] on the GHC trac, attaching the (revised if necessary) patch. As well as the description and rationale, include a link to the discussion in the mailing list archives, as well as a summary of the conversation (the summary is needed for anyone wondering about the change later: it's not reasonable to point people at a 50-message thread (but please do include a link to the thread in the list archives too, so that people can review it if they wish)).<br />
<br />
Here is an example of how to [http://hackage.haskell.org/trac/ghc/ticket/966 summarise a successful submission].<br />
<br />
== See also ==<br />
<br />
* [http://hackage.haskell.org/trac/ghc/wiki/WorkingConventions GHC Working Conventions], including guidelines for submitting patches via darcs.<br />
* [http://haskell.org/haskellwiki/Category:Style Notes on programming style]<br />
<br />
[[Category:Community]]<br />
[[Category:Proposals| ]]</div>Simonpjhttps://wiki.haskell.org/index.php?title=Library_submissions/OldProcess&diff=40481Library submissions/OldProcess2011-06-10T07:33:57Z<p>Simonpj: New page: = THE OLD LIBRARY PROCESSS, NOW SUPERCEDED = This page describes the old library process, which was superceded in June 2011. It's preserved here only for old times sake. See the new pr...</p>
<hr />
<div>= THE OLD LIBRARY PROCESSS, NOW SUPERCEDED =<br />
<br />
This page describes the old library process, which was superceded in June 2011. It's preserved here only for old times sake. <br />
See the new process at [[Library_submissions]]<br />
<br />
---------------------------------------------<br />
<br />
As the Haskell community has grown, and emphasis on development has<br />
moved from language to libraries, the need for a more formalised process<br />
for contributing to libraries has emerged. This page documents our<br />
'best practices' for proposing changes to library interfaces<br />
(e.g. new modules or functions, removing functions) in packages that list ''libraries@haskell.org'' as maintainer.<br />
We have been using it since October 2006.<br />
<br />
In essence, we don't want proposals to go unnoticed, but changes to<br />
basic interfaces also need thorough consideration. <br />
<br />
== Creating a proposal ==<br />
<br />
In order to ensure we have something concrete to discuss, please follow<br />
the following guidelines:<br />
<br />
* ''Currency''. Make your changes against a copy of the HEAD branch of the [http://hackage.haskell.org/trac/ghc/wiki/DarcsRepositories relevant library], and make sure it compiles.<br />
* ''Portability''. Code should be portable. If it is not portable, reasons should be given. At the very least ensure the code runs in Hugs and GHC, and on Windows and Linux.<br />
* ''Style''. Follow the conventions in the library you are modifying.<br />
* ''Documentation''. It must include valid [http://haskell.org/haddock Haddock] documentation.<br />
* ''Tests''. Code should ideally also come with suitable tests for the testsuite. There's currently some disagreement about what this means. Discussion of where we may want to head is in the [[library tests]] page.<br />
<br />
== Submitting the proposal ==<br />
<br />
* ''Patch''. Create a [http://darcs.net darcs] or git patch (depending on what sort of repo the library lives in) of your change using <tt>darcs record</tt> or <tt>git commit -a</tt>, including a rationale for the change. Save the patch to a file, using <tt>darcs send --output</tt> or <tt>git format-patch</tt>.<br />
<br />
* ''Submission''. Start a new thread on the libraries@haskell.org mailing list (which you need to [http://www.haskell.org/mailman/listinfo/libraries subscribe] to before posting), with a subject beginning "Proposal:". Include a description of the change and the rationale, and attach the patch. You may wish to include a pointer to updated Haddock documentation, if relevant. You must also include a deadline for the discussion period; it must allow at least 2 weeks for discussion, but you may allow more - particularly if many people are likely to be away during the next 2 weeks. If discussion is still ongoing at the deadline, the discussion period can be extended.<br />
<br />
If someone has done all this, they are entitled to expect feedback;<br />
silence during the discussion period can be interpreted as consent.<br />
<br />
== At the end of the discussion period ==<br />
<br />
* Determine whether consensus for the change was reached. A deeply held disagreement at this point may require some form of governance (voting, dictatorship, etc). This should be a rare event.<br />
<br />
* If consensus was achieved, file a [http://hackage.haskell.org/trac/ghc/newticket ticket] on the GHC trac, attaching the (revised if necessary) patch. As well as the description and rationale, include a link to the discussion in the mailing list archives, as well as a summary of the conversation (the summary is needed for anyone wondering about the change later: it's not reasonable to point people at a 50-message thread (but please do include a link to the thread in the list archives too, so that people can review it if they wish)).<br />
<br />
Here is an example of how to [http://hackage.haskell.org/trac/ghc/ticket/966 summarise a successful submission].<br />
<br />
== See also ==<br />
<br />
* [http://hackage.haskell.org/trac/ghc/wiki/WorkingConventions GHC Working Conventions], including guidelines for submitting patches via darcs.<br />
* [http://haskell.org/haskellwiki/Category:Style Notes on programming style]<br />
<br />
[[Category:Community]]<br />
[[Category:Proposals| ]]</div>Simonpjhttps://wiki.haskell.org/index.php?title=GHC/As_a_library&diff=40473GHC/As a library2011-06-09T14:27:25Z<p>Simonpj: /* Links */</p>
<hr />
<div>''For instructions on the GHC API with GHC 6.8 or older please refer to [[GHC/As a library (up to 6.8)]]''<br />
<br />
__TOC__<br />
<br />
== Introduction ==<br />
<br />
GHC's functionality can be useful for more things than just compiling Haskell programs. Important use cases are programs that analyse (and perhaps transform) Haskell code. Others include loading Haskell code dynamically in a GHCi-like manner. For this reason, a lot of GHC's features can be accessed by programs which import the <tt>ghc</tt> package.<br />
<br />
The instructions on this page concern the API of GHC 6.10.1 and above. Please note that the GHC API is still in flux and may change quite significantly between major releases while we (the GHC team) provide new features or simplify certain aspects.<br />
<br />
<br />
== Getting Started ==<br />
<br />
To use the GHC API you need GHC 6.10.1 or above and import the <tt>ghc</tt> package.<br />
<pre><br />
ghc -package ghc my_program.hs<br />
</pre><br />
In most cases you probably also want to use the [http://hackage.haskell.org/cgi-bin/hackage-scripts/package/ghc-paths ghc-paths package].<br />
<br />
Most of the common functionality is provided by the <tt>GHC</tt> module, but occasionally you may have to import other modules. See the GHC's [http://www.haskell.org/ghc/docs/latest/html/libraries/ghc/index.html haddock documentation] for a list of these modules. One good entry point into the docs is [http://www.haskell.org/ghc/docs/latest/html/libraries/ghc/GHC.html GHC].<br />
== A Simple Example ==<br />
<br />
The following little program essentially does what <tt>ghc --make</tt> does.<br />
<br />
<haskell><br />
import GHC<br />
import GHC.Paths ( libdir )<br />
import DynFlags ( defaultDynFlags )<br />
<br />
main = <br />
defaultErrorHandler defaultDynFlags $ do<br />
runGhc (Just libdir) $ do<br />
dflags <- getSessionDynFlags<br />
setSessionDynFlags dflags<br />
target <- guessTarget "test_main.hs" Nothing<br />
setTargets [target]<br />
load LoadAllTargets<br />
</haskell><br />
<br />
The outermost function, <tt>defaultErrorHandler</tt>, sets up proper exception handlers and prints an error message and exits with exit code 1 if it encounters one of these exceptions.<br />
<br />
Most of GHC's high-level API requires access to a current session. Therefore, these functions require to be called inside a monad that is an instance of the <tt>GhcMonad</tt> typeclass. Two default implementations of this typeclass are <tt>Ghc</tt> and <tt>GhcT</tt>. In the above example we used the <tt>Ghc</tt> monad since we don't need to track any extra state.<br />
<br />
The argument to <tt>runGhc</tt> is a bit tricky. GHC needs this to find its libraries, so the argument must refer to the directory that is printed by <tt>ghc --print-libdir</tt> for the ''same'' version of GHC that the program is being compiled with. Above we therefore use the <tt>ghc-paths</tt> package which provides this for us.<br />
<br />
== Another example ==<br />
<br />
Here we demonstrate calling [http://www.haskell.org/ghc/docs/latest/html/libraries/ghc/GHC.html#v:parseModule parseModule], [http://www.haskell.org/ghc/docs/latest/html/libraries/ghc/GHC.html#v:typecheckModule typecheckModule], [http://www.haskell.org/ghc/docs/latest/html/libraries/ghc/GHC.html#v:desugarModule desugarModule], [http://www.haskell.org/ghc/docs/latest/html/libraries/ghc/GHC.html#v:getNamesInScope getNamesInScope], and [http://www.haskell.org/ghc/docs/latest/html/libraries/ghc/GHC.html#v:getModuleGraph getModuleGraph]. This works for haskell-platform, ghc-7.0.3. It also demonstrates how to enable some extensions.<br />
<br />
<haskell><br />
--A.hs<br />
--invoke: ghci -package ghc A.hs<br />
<br />
import GHC<br />
import Outputable<br />
<br />
import GHC.Paths ( libdir )<br />
--GHC.Paths is available via cabal install ghc-paths<br />
<br />
import DynFlags<br />
targetFile = "B.hs"<br />
<br />
main = do<br />
res <- example<br />
putStrLn $ showSDoc ( ppr res )<br />
<br />
example = <br />
defaultErrorHandler defaultDynFlags $ do<br />
runGhc (Just libdir) $ do<br />
dflags <- getSessionDynFlags<br />
let dflags' = foldl xopt_set dflags<br />
[Opt_Cpp, Opt_ImplicitPrelude, Opt_MagicHash]<br />
setSessionDynFlags dflags<br />
target <- guessTarget targetFile Nothing<br />
setTargets [target]<br />
load LoadAllTargets<br />
modSum <- getModSummary $ mkModuleName "B"<br />
p <- parseModule modSum<br />
t <- typecheckModule p<br />
d <- desugarModule t<br />
l <- loadModule d<br />
n <- getNamesInScope<br />
c <- return $ coreModule d<br />
<br />
g <- getModuleGraph<br />
mapM showModule g <br />
return $ (parsedSource d,"/n-----/n", typecheckedSource d)<br />
</haskell><br />
<br />
<haskell><br />
--B.hs<br />
module B where<br />
<br />
main = print "Hello, World!"<br />
<br />
</haskell><br />
<br />
== Links ==<br />
<br />
* [http://www.haskell.org/ghc/docs/latest/html/libraries/ghc/index.html GHC API haddock]<br />
* [http://mistuke.wordpress.com/category/vsx/ Great blog post] about using the GHC API to get "QuickInfo" in a Visual Studio binding for Haskell.</div>Simonpjhttps://wiki.haskell.org/index.php?title=Library_submissions/NewDraft&diff=40452Library submissions/NewDraft2011-06-08T06:56:55Z<p>Simonpj: /* The Core Libraries */</p>
<hr />
<div>DRAFT 19 May 2011<br />
<br />
This page describes a proposed process for maintaining the <br />
'''Core libraries'''. The core libraries are a subset of the packages in the<br />
Haskell Platform, and define basic APIs that are expected to be<br />
available in any Haskell implementation. They are listed under "The Core Libraries" below.<br />
<br />
In the past we used the [[Library_submissions]] process for the core libraries, but that was deemed to hamper productivity too much. The new policy puts more emphasis on leadership and empowers individual maintainers to make changes, while still allowing the community to make feedback, contributions, and proposals.<br />
<br />
Non-core libraries are, of course, managed by their own authors/maintainers (named in their .cabal file), using whatever policies those maintainers see fit. [Note: arguably the policies below might usefully be applied to all libraries embodied in the Haskell Platform, but that is a question for the HP team.]<br />
<br />
= General principles =<br />
<br />
* Each core package has a named maintainer, or small group of maintainers, who have commit access to the package. <br />
<br />
* Third parties are encouraged to make proposals for changes, both to the library API and its implementation, by sending the proposal to the maintainer (CC'ing the libraries mailing list).<br />
<br />
* The maintainer is trusted to decide what changes to make to the package, and when. They are strongly encouraged to follow the guidance below, but the general principle is: the community offers opinions, but the maintainers decide.<br />
<br />
<br />
= Responsiveness =<br />
<br />
* Third parties submitting proposals to the maintainer of a library can expect a timely and thoughtful response. <br />
* The more effort the proposer invests (for example, by constructing a patch rather than making an off-the-cuff suggestion) the more consideration s/he can reasonably expect.<br />
* Proposals that have widespread support, and are accompanied by patches (preferably with tests and documentation), should normally be accepted by the maintainer. <br />
* It is up to the maintainer to decide what "widespread" means; in particular, it does not always mean "a majority of those who responded". The majority-responder story is vulnerable to selection bias; e.g. 7 people (out of a client base of hundreds) say "add this function" but the maintainer thinks it will make the interface incrementally more complicated without sufficient benefit.<br />
* Where there is significant work involved in implementing a proposal, it is reasonable for a maintainer to ask for a patch. The principle is that maintainers are not obliged to do the work of implementing a proposal, even if it does enjoy wide support. For more substantial changes, it makes sense to develop the implementation in dialogue with the maintainer.<br />
<br />
= Guidance for proposers =<br />
<br />
A "proposal" can be anything from a one-sentence suggestion to a fully-implemented, tested, and documented patch.<br />
However, the more substantial the proposal the more attention you can expect. The process is this:<br />
<br />
* Send your proposal by email to the maintainer, with a copy to the libraries@haskell.org mailing list (which you need to [http://www.haskell.org/mailman/listinfo/libraries subscribe] to before posting).<br />
<br />
* Set a deadline for discussion (no less than two weeks), and act as chair/moderator for the discussion. <br />
<br />
* At the end of the discussion period, summarise your understanding of the consensus (or lack thereof), including a link to the thread in the mailing list archives, and send the summary to the maintainer for decision. The deadline gives you a moment to summarise the debate and hand over to the maintainer. It isn't a deadline for the maintainer to decide; for example he or she may seek more discussion first. <br />
<br />
* If the decision is positive, [http://hackage.haskell.org/trac/ghc/newticket create a ticket] on the GHC trac. The description of the ticket can summarise the proposal and link to the mail thread. Further discussion and implementation patches can be attached to the ticket, and the ticket helps the maintainer to keep track of what is on the go. (Obviously if the maintainer prefers some other mechanism, follow his or her guidance.)<br />
<br />
* For non-trivial changes the maintainer may ask for a patch. You may create the patch up front, and make it part of your proposal; or you may want to have some discussion about the design first, and only then roll up your sleeves to do the implementation; and for bigger jobs you may want to wait until the maintainer agrees in principle with the change.<br />
<br />
Here are desirable properties for a proposal and its implementation. The more of these properties your proposal or patch has, the more likely it is that the maintainer will adopt your idea. After all, to adopt it the maintainter will have to do whatever tasks you didn't do.<br />
<br />
* '''Description'''. A good proposal says clearly ''what'' you propose, ''why'' it is a good idea, and what its consequences would be.<br />
* '''Patch'''. Use <tt>darcs record</tt> or <tt>git commit</tt> (depending on what sort of repo the library lives in) to create it. Save the patch to a file, using <tt>darcs send --output</tt> or <tt>git format-patch</tt>. Make your changes against a copy of the master branch of the relevant library, and make sure it compiles.<br />
* '''Portability'''. Good code is portable. In particular, try to ensure the code runs in Hugs and GHC, and on Windows and Linux.<br />
* '''Style'''. Good code follows the conventions in the library you are modifying.<br />
* '''Documentation'''. Good code includes valid [http://haskell.org/haddock Haddock] documentation.<br />
* '''Tests'''. Good patches have suitable tests for the library's testsuite.<br />
<br />
= Guidance for maintainers =<br />
<br />
The principle is that we '''trust the maintainer''' to behave sensibly. The guidelines below are just that: guidelines, not rules. Still, the core libraries are used by many, many people, so maintainers should make every effort not to mess them up by accident. <br />
<br />
* '''API changes should be discussed''' on the libraries mailing list prior to making the change, even if the maintainer is the proposer. The maintainer still has ultimate say in what changes are made, but the community should have the opportunity to comment on changes. However, unaminity (or even a majority) is not required.<br />
<br />
* '''Every API change should be described precisely in the commit log.''' The commit logs should be sent to a public mailing list, or otherwise made easily available (e.g. via github), so that the community can keep an eye on changes and comment.<br />
<br />
* '''Backwards compatibility''' is important to many users. API changes are expected to retain backwards compatibility wherever possible. However, from time to time we may decide to have major revisions which are explicitly not backwards compatible; in these cases we may try to make the previous version of the package available concurrently, as in the base-3/base-4 switchover.<br />
<br />
* You don't need to consult the community for '''purely internal changes'''; i.e. changes that do not affect the library's clients.<br />
<br />
* Changes that simply '''widen the API by adding new functions''' are a bit of a grey area. It's better to consult the community, becuase there may be useful feedback about (say) the order of arguments, or the name of the function, or whatnot. On the other hand few clients will actually break if you add a new function to the API. Use your judgement.<br />
<br />
Libraries maintained by the GHC team are subject to the GHC validation policy - patches will be tested for validation before committing. Those packages not maintained by the GHC team will probably have a GHC lagging mirror repository that is subject to validation.<br />
<br />
= The Core Libraries =<br />
<br />
The "core libraries" are by definition the ones that (until now) have listed their maintainer as "libraries@haskell.org". The following packages constitute the core libraries:<br />
<br />
{| border="1"<br />
! Package !! Maintainer<br />
|-<br />
| [http://hackage.haskell.org/package/array array] || GHC HQ<br />
|-<br />
| [http://hackage.haskell.org/package/base base] || GHC HQ<br />
|-<br />
| [http://hackage.haskell.org/package/containers containers] || Johan Tibell and Milan Straka<br />
|-<br />
| [http://hackage.haskell.org/package/directory directory] || GHC HQ<br />
|-<br />
| [http://hackage.haskell.org/package/mtl mtl] || Edward Kmett<br />
|-<br />
| [http://hackage.haskell.org/package/pretty pretty] || David Terei<br />
|-<br />
| [http://hackage.haskell.org/package/process process] || GHC HQ <br />
|-<br />
| [http://hackage.haskell.org/package/random random] || Daniel Fischer<br />
|-<br />
| [http://hackage.haskell.org/package/unix unix] || GHC HQ<br />
|-<br />
|-<br />
| [http://hackage.haskell.org/package/template-haskell template-haskell] || GHC HQ<br />
|-<br />
| [http://hackage.haskell.org/package/parallel parallel] || Simon Marlow<br />
|-<br />
| [http://hackage.haskell.org/package/hpc hpc] || Andy Gill <br />
|-<br />
| [http://hackage.haskell.org/package/ghc-prim ghc-prim] || GHC HQ <br />
|-<br />
| [http://hackage.haskell.org/package/extensible-exceptions extensible-exceptions] || GHC HQ <br />
|-<br />
| [http://hackage.haskell.org/package/deepseq deepseq] || Simon Marlow<br />
|-<br />
| [http://hackage.haskell.org/package/Win32 Win32] || Volunteer needed <br />
|}<br />
<br />
* The maintainer "GHC HQ" means Simon Marlow, Simon Peyton Jones, and Ian Lynagh. <br />
* "Volunteer needed" means that GHC HQ is the default maintainer, but that we'd like someone else to volunteer please!<br />
<br />
The following packages match the appropriate language standard, and as such cannot change independently. The code is maintained by the GHC team.<br />
<br />
{| border="1"<br />
|-<br />
| [http://hackage.haskell.org/package/haskell2010 haskell2010] || GHC HQ<br />
|-<br />
| [http://hackage.haskell.org/package/haskell98 haskell98] || GHC HQ<br />
|}<br />
<br />
These packages are maintained only for backward compatibility, and are not expected to undergo API changes in the future. <br />
<br />
{| border="1"<br />
|-<br />
| [http://hackage.haskell.org/package/old-locale old-locale] || GHC HQ <br />
|-<br />
| [http://hackage.haskell.org/package/old-time old-time] || GHC HQ <br />
|}<br />
<br />
= See also =<br />
<br />
* [http://hackage.haskell.org/trac/ghc/wiki/WorkingConventions GHC Working Conventions], including guidelines for submitting patches via darcs.<br />
* [http://haskell.org/haskellwiki/Category:Style Notes on programming style]<br />
<br />
[[Category:Community]]<br />
[[Category:Proposals| ]]</div>Simonpj