1 %%% This is a LaTeX2e style file.
3 %%% It supports setting functional languages, such as Haskell.
5 %%% Manuel M. T. Chakravarty <chak@cse.unsw.edu.au> [1998..2002]
7 %%% $Id: haskell.sty,v 1.2 2004/04/02 08:47:53 simonmar Exp $
9 %%% This file is free software; you can redistribute it and/or modify
10 %%% it under the terms of the GNU General Public License as published by
11 %%% the Free Software Foundation; either version 2 of the License, or
12 %%% (at your option) any later version.
14 %%% This file is distributed in the hope that it will be useful,
15 %%% but WITHOUT ANY WARRANTY; without even the implied warranty of
16 %%% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 %%% GNU General Public License for more details.
19 %%% Acknowledegments ==========================================================
21 %%% Thanks to Gabriele Keller <keller@it.uts.edu.au> for beta testing and
22 %%% code contributions. Thanks to the LaTeX3 project for improving the LaTeX
23 %%% sources (which helped me writing this code). Furthermore, I am grateful
24 %%% to Martin Erwig <Martin.Erwig@FernUni-Hagen.de> and Bernard J. Pope
25 %%% <bjpop@cs.mu.OZ.AU> for feedback and suggestions, and to Conal Elliott
26 %%% <conal@MICROSOFT.com> and Marc van Dongen <dongen@cs.ucc.ie> for pointing
29 %%% TODO ======================================================================
31 %%% B ~ bug; F ~ feature
33 %%% * B: Consider to use the following alternative definition for \<..\>:
35 %%% \def\<{\bgroup\@hsSpaceToApp\endhs}
36 %%% \def\endhs#1\>{\(\mathit{#1}\)\egroup}
38 %%% It completely avoids the problem that \mathit\bgroup..\egroup isn't
39 %%% guaranteed to work and seems more elegant, anyway.
41 %%% * F: Along the lines of the discussion with Martin Erwig add support for
42 %%% keywords etc (see the emails)
44 %%% * B: If we have as input
49 %%% there won't be a `\hsap' inserted!! (Can this be solved by using
50 %%% \obeylines in \<...\>?)
52 %%% * B: A \relax is needed after a & if it immediately followed by a \hsbody{}
53 %%% (See TeXbook, S.240)
55 %%% * F: Implement a \hstext{...} as \(\text{...}\).
57 %%% * F: Star-form of \hscom that uses "---" instead of "-\hskip0pt-"
59 %%% * We would like hswhere* etc that are like haskell* (\hsalign already
60 %%% supports this, ie, there is a \hsalign*).
62 %%% * Star-Versions of if, let etc that use a single line layout (maybe not
63 %%% with star, because of the above).
65 %%% * Support for enforcing and prohibiting breaks in `haskell' displays.
67 %%% * Comments in a let-in should be aligned in the same way for the bindings
70 %%% * It would be nice to have different styles (indentation after in of
71 %%% let-in or not) etc; either to be set with a package option or in the
72 %%% preamble (the latter probably makes more sense).
74 %%% * Literate programming facility: Variant of the `haskell' env (maybe
75 %%% `hschunk', which is named and can be used in other chunks). But maybe
76 %%% it is not necessary to provide a chunk-based reordering mechanism,
77 %%% because most of the Haskell stuff can be in any order anyway...
78 %%% Important is to provide a way to define visually pleasing layout
79 %%% together with the raw Haskell form for program output. (Maybe `haskell*'
80 %%% as Haskell env that outputs its contents?)
86 \NeedsTeXFormat{LaTeX2e}
87 \ProvidesPackage{haskell}[2002/02/08 v1.1a Chilli's Haskell Style]
89 % NOTE: The sole purpose of the following is to work around what I believe is
90 % a bug in LaTeX. If the first occurence of \mathit in a document uses
91 % \bgroup and \egroup to enclose the argument (instead of { and }),
92 % \mathit does *not* apply to the argument. (I guess, some font
93 % initialisation stuff is getting in the way of parsing the argument.)
95 % The following forces a \mathit right after \begin{document}.
97 % UPDATE: The LaTeX project people say that it isn't really a bug; more
98 % like a not supported form. See alternative definition in the
101 \AtBeginDocument{\setbox0=\hbox{\(\mathit\relax\)}}
108 \hsmargin\leftmargini
111 %% Main macros and environments
112 %% ============================
116 \newcommand{\hsap}{% % application by juxtaposition
117 \unskip\mskip 4mu plus 1mu} % only the last \hsap counts
119 % commands to start and stop setting spaces as \hsap
121 {\obeyspaces\gdef\@hsSpaceToApp{\obeyspaces\let =\hsap}} % spaces matter!!!
122 {\obeyspaces\gdef\@hsNormalSpace{\let =\space}}
124 % commands to start and stop treating numbers specially, ie, we don't want
125 % them to be affected by font changing commands in Haskell contexts as this
126 % would give italic numerals; the trick is to redefine their math code such
127 % that they go into math class 0 and thus don't change families (cf. `The
128 % TeXbook', Chapter 17, pp152)
130 \newcommand{\@hsRmNumbers}{%
142 \newcommand{\@hsNormalNumbers}{%
155 % Save the bindings of the standard math commands
157 % This is somewhat subtle as we want to able to enter the original math mode
158 % within Haskell mode and we have to ensure that the different opening
159 % commands are matched by the correct versions of the closing commands.
162 \let\@hsmathendorg=\)
164 \newcommand{\@hsmath}{%
173 \newcommand{\@hsmathend}{%
177 \newcommand{\@hsmathorgx}{%
179 \let\)=\@hsmathendorg
182 %% Typesetting of Haskell
183 %% ======================
185 % Inline Haskell phrases are delimited by `\<' and `\>'.
187 % Note: `\>' is only locally redefined.
196 \def\\{\cr} % for Haskell alignments
198 \newcommand{\@endhs}{%
203 % Displayed Haskell (environment `haskell' and `haskell*')
205 % There are two kind of preambles for \halign: \hs@preambleNorm is for
206 % `amsmath' style alignments and \hs@preambleStar for `equation' style
207 % alignments (but with an unbound number of columns to its right)
209 % We need #### to get a ## in the \edef building the \halign command.
211 % first the preambles (also used in \hs@align below):
213 \def\hs@preambleNorm{%
214 \noexpand\<####\unskip\noexpand\>\hfil&&\noexpand%
215 \<{}####\unskip\noexpand\>\hfil}
216 \def\hs@preambleStar{%
217 \noexpand\<####\unskip\noexpand\>\hfil&\hfil\noexpand%
218 \<{}####\unskip{}\noexpand\>\hfil&&\noexpand\<{}####\noexpand\>\hfil}
222 \newenvironment{haskell}{%
223 \@haskell\hs@preambleNorm}{%
226 \newenvironment{haskell*}{%
227 \@haskell\hs@preambleStar}{%
231 % auxiliary definition getting the preamble as its first argument and starting
236 \vspace\abovedisplayskip
237 \let\(=\@hsmath % Important when `\(' occurs after `&'!
239 \halign\bgroup\hskip\hsmargin#1\cr}
243 % Auxiliary definition ending environment:
247 % \vspace\belowdisplayskip
248 \egroup\noindent\ignorespaces\global\@ignoretrue%
251 % single line comment and keyword style
253 \newcommand{\hscom}[1]{%
254 \relax\(\quad\textnormal{-\hskip0pt- #1}\)}
255 % \relax\(\quad\textnormal{--- #1}\)}
256 \newcommand{\hskwd}[1]{%
259 % informal description
261 \newcommand{\hsinf}[1]{%
262 \(\langle\textnormal{#1}\rangle\)}
264 % literals and some special symbols
266 \newcommand{\hschar}[1]{\textrm{'#1'}} % character literals
267 \newcommand{\hsstr}[1]{\textrm{``#1''}} % strings literals
268 \newcommand{\hsfrom}{\leftarrow} % <-
272 % check for an optional star and combine prefix (in #1) with one of the two
273 % preambles (with star means to center the material between the first and
278 {\hs@align@pre{#1\hs@preambleStar}}%
279 {\hs@align@pre{#1\hs@preambleNorm}}%
282 % test for optional argument; #1: preamble
284 \def\hs@align@pre#1{%
285 \@testopt{\hs@align@prealign#1}t}
287 % got all arguments, now for the real code; #1: preamble; #2: alignment;
288 % #3: body (the material set by the \halign)
290 \def\hs@align@prealign#1[#2]#3{%
294 \if #2t\vtop \else \if#2b\vbox \else \vcenter \fi\fi
302 % user-level command: alignment without a prefix
304 \newcommand{\hsalign}{%
309 % subphrase breaking the surrounding alignment being flushed left
311 \newcommand{\hsnoalign}[1]{%
313 \hs@align{\hskip\hsmargin}{#1}%
317 % body expression breaking the surrounding alignment
319 % * setting \hsmargin to 0pt within the preamble (and _after_ it is used in
320 % the preamble) is crucial, as we want \hsmargin only to be applied in
321 % _outermost_ alignments
323 \newcommand{\hsbody}[1]{%
326 \hs@align{\hskip\hsmargin\quad\hsmargin0pt}{#1}%
331 %% Defining commands for use in the Haskell mode
332 %% =============================================
334 %% We use some of the low-level machinery defined in LaTeX's source file
337 %% \hscommand is similar to \newcommand, but there is no *-version.
339 %% We use our own definitions here to insert a strategic `\relax' (see below)
340 %% and to obey spaces within the bodies of Haskell definitions.
342 \newcommand{\hscommand}[1]{\@testopt{\hs@newcommand#1}0}
343 \def\hs@newcommand#1[#2]{%
344 \obeyspaces % spaces count in Haskell macros
345 \@ifnextchar [{\hs@xargdef#1[#2]}%
348 % All this trouble only to be able to add the `\relax' into the expansion
349 % process. If we don't that, commands without optional arguments when
350 % invoked after an alignment character & don't work properly (actually, the
351 % \obeyspaces doesn't work). I am sure that has to do with the scanning for
352 % \omit etc in \halign (TeXbook, p240), but I don't understand yet why it
353 % is problematic in this case.
355 % Furthermore, we switch off \obeyspaces in the end.
357 \long\def\hs@argdef#1[#2]#3{%
359 \expandafter\def\expandafter#1\expandafter{%
360 \relax % in order to stop token expansion after &
361 \csname\string#1\expandafter\endcsname}%
362 \expandafter\@yargdef
363 \csname\string#1\endcsname
367 \catcode`\ =10% % stop obeying spaces now
370 % Switch off \obeyspaces in the end.
372 \long\def\hs@xargdef#1[#2][#3]#4{%
374 \expandafter\def\expandafter#1\expandafter{%
379 \csname\string#1\expandafter\endcsname
381 \expandafter\@yargdef
382 \csname\string#1\endcsname
386 \catcode`\ =10% % stop obeying spaces now
395 \newcommand{\hsapp}{\mathbin{+\mkern-7mu+}}
396 \newcommand{\hsifix}[1]{\mathbin{\string`#1\string`}}
400 \hscommand{\hslet}[3][t]{%
411 \hscommand{\hsif}[4][t]{%
413 \hskwd{if} #2 \hskwd{then}\\
422 \hscommand{\hscase}[3][t]{%
424 \hskwd{case} #2 \hskwd{of}\\
431 % * it is important to take the \quad into the preamble, so that nested
432 % \noaligns can break it
434 \hscommand{\hswhere}[1]{%
437 \hs@align{\quad}{#1}%
443 \hscommand{\hsdo}[2][t]{%
452 \hscommand{\hsclass}[2]{%
453 \hskwd{class} #1 \hskwd{where}
459 % instance declaration
461 \hscommand{\hsinstance}[2]{%
462 \hskwd{instance} #1 \hskwd{where}
469 %% Extensions for Distributed Haskell (Goffin)
470 %% ===========================================
472 %% These definitions may change in the future.
474 \hscommand{\hsunif}{\mathbin{:=:}}
475 \hscommand{\hsalias}{\mathrel{\sim}}
476 \hscommand{\hsoutof}{\twoheadleftarrow}
477 \hscommand{\hsinto}{\twoheadrightarrow}
478 \hscommand{\hsparc}{\binampersand}
479 \hscommand{\hsseq}{\Longrightarrow}
480 \hscommand{\hsex}[2]{{\hskwd{ex} #1 \hskwd{in} #2}}
482 \hscommand{\hsexin}[3][t]{%
484 \hskwd{ex} #2 \hskwd{in}\\
489 \hscommand{\hschoice}[2][t]{%