packages feed

free-theorems-webui-0.1: lambdaTeX.tex

% Copyright © 2000 Patryk Zadarnowski «pat@jantar.org»
%
% Redistribution  and  use  in  source  and  binary  forms,  with  or  without
% modification, are permitted provided  that the following conditions are met:
% (1) Redistributions of  source code must retain the  above copyright notice,
% this list  of conditions and the following  disclaimer.  (2) Redistributions
% in  binary form  must reproduce  the above  copyright notice,  this  list of
% conditions and  the following disclaimer  in the documentation  and/or other
% materials provided  with the distribution.  (3)  The name of  any author may
% not  be used  to  endorse or  promote  products derived  from this  software
% without their specific prior written permission.
%
% THIS SOFTWARE IS  PROVIDED ``AS IS'' AND ANY  EXPRESS OR IMPLIED WARRANTIES,
% INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
% FITNESS FOR  A PARTICULAR  PURPOSE, ARE DISCLAIMED.   IN NO EVENT  SHALL THE
% AUTHORS BE LIABLE FOR  ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
% OR  CONSEQUENTIAL DAMAGES  (INCLUDING, BUT  NOT LIMITED  TO,  PROCUREMENT OF
% SUBSTITUTE  GOODS OR SERVICES;  LOSS OF  USE, DATA  OR PROFITS;  OR BUSINESS
% INTERRUPTION)  HOWEVER CAUSED  AND ON  ANY THEORY  OF LIABILITY,  WHETHER IN
% CONTRACT,  STRICT LIABILITY,  OR  TORT (INCLUDING  NEGLIGENCE OR  OTHERWISE)
% ARISING IN ANY WAY  OUT OF THE USE OF THIS SOFTWARE,  EVEN IF ADVISED OF THE
% POSSIBILITY OF SUCH DAMAGE.


%% lambdaTeX v1.0.5 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% Limitations:
%
%       - no support for nested comments
%       - no support for LaTeX mode
%       - no support for non-literate mode
%       - no support for strings in inline mode
%       - function names must be marked as such explicitely
%       - < > as the first character in math mode don't work.
%       - code lines don't wrap well.
%
% Quirks:
%
%       1. HaskellTeX reserves <, > and " as active characters, but, of
%          course restores their meaning of < and > in math mode. However,
%          this doesn't work as well as expected. When TeX sees the $
%          character, it reads the following character to see if it is
%          another $ beginning a math display. If that character is active,
%          it attempts to expand it (a bug in TeX?! or just a mis-feature?
%          I couldn't find anything in the TeXbook.) So, you must write
%          $ >$ rather than $>$. Oh well. To make amends for this, I define
%          \lt and \gt math macros to complement \le and \ge already in
%          plain TeX, as $\gt$ looks better than $ >$. Fortunately, one rarely
%          needs to write a relational operator as the first character in
%          a formula, and, of course, $a>b$ works as expected.
%
%       2. When parsing comments, the lexical analyzer temporarily switches
%          out of Haskell mode, so normal fonts, etc can take effect.
%          Specifically, it switches out of TeX mode after processing the
%          initial <dashes> token of a comment. This means that it must
%          process the token immediately following the dashes, too, before
%          leaving Haskell mode. Therefore, if this token is an active
%          character, it will not work as expected (its category code will
%          be 12.) Again, this normally is not a problem as the character
%          immediately following the -- should be a space, anyway.

\catcode`@=11

\newskip\hsparskip      \hsparskip=8pt
\newdimen\hsleftskip    \hsleftskip=30pt
\newdimen\hsrightskip   \hsrightskip=10pt
\newdimen\hscommentskip \hscommentskip=1em
\newdimen\hswordspace   \hswordspace=.3em
\newdimen\hsspacewidth  \hsspacewidth=1em
\newdimen\hstabwidth    \hstabwidth=8em

\def\everyhs{}
\def\beforehs{\vskip 14pt plus3pt minus1pt}
\def\afterhs{\vskip 14pt plus3pt minus1pt}

\font\hs@keyface=phvb at 9pt
\font\hs@funface=phvr at 9pt
\font\hs@sfunface=phvr at 7pt % (added by florian)
\font\hs@varface=phvro at 9pt
\font\hs@conface=phvrc at 9pt
\font\hs@numface=phvr at 9pt
\font\hs@strface=pcrr at 9pt
\font\hs@symface=phvr at 9pt
\font\hs@ssymface=phvr at 7pt
\font\hs@sssymface=phvr at 5.8pt

\hyphenchar\hs@keyface=-1
\hyphenchar\hs@funface=-1
\hyphenchar\hs@varface=-1
\hyphenchar\hs@conface=-1
\hyphenchar\hs@symface=-1
\hyphenchar\hs@numface=-1
\hyphenchar\hs@strface=-1
\hyphenchar\hs@ssymface=-1
\hyphenchar\hs@sssymface=-1


%%% Lexical modes %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% The lexical analyzer can operate in one of three modes:
%
%       0. Inline - Haskell code appearing within a paragraph
%       1. Bird   - Bird-style literate Haskell code
%
% The Inline mode is used to typeset a short fragment of Haskell code
% in the middle of a paragraph, for example when referring to a variable
% defined within the program. The mode is entered by the " character.
% The lexical analyzer exits when it encounters another " character.
% Newlines are treated as simple whitespace, and comments are illegal.
% Because the " character is reserved, strings cannot appear in the Inline
% mode.
%
% The Bird mode is used to process Bird-style literate scripts. The mode
% is entered by the > character (note that this is a hack - in Haskell, >
% designates literate code only when it appears as the first character on
% a line.) The mode exits when it encounters a blank line. The text is typeset
% as a separate paragraph, idented by \hsleftskip on the left and \hsrightskip
% on the right. The \beforehs macro is inserted before the fragment of code
% and \afterhs is inserted after it. The > character itself is not displayed.

% In both modes, the \everyhs macro is inserted immediately after entering
% the Haskell mode.
%
% One thing worth noting is that, because spaces are skipped following active
% characters, in the Inline mode any spaces immediately following the operning
% " are ignored. For consistency, we also ignore any spaces preceeding the
% closing ". In Bird mode, TeX swallows spaces following the opening >, so
% the lexical analyzer _assumes_ that the > was followed by a single space,
% and strips one space-worth of indentation from all remaining lines in the
% code fragment.

\newif\ifhs@inline

% The \lambdaTeX macro:
\def\lambdaTeX{$\lambda$\kern-1.5pt\TeX}

% The amount to kern the current token by:
\newdimen\hs@space
\newdimen\hs@guardpos
\newdimen\hs@previndent
\newdimen\hs@indent

% The boxes used to build up the current line:
\newbox\voidb@x % permanently void
\newbox\hs@i
\newbox\hs@ii
\newbox\hs@iii

% Macros for requesting special formatting of a specific lexeme:
\def\typeset#1#2{\expandafter\def\csname<#1>\endcsname{#2}}

% Define the Haskell keywords:
\typeset{case}{{\hs@keyface case}}
\typeset{class}{{\hs@keyface class}}
\typeset{data}{{\hs@keyface data}}
\typeset{default}{{\hs@keyface default}}
\typeset{deriving}{{\hs@keyface deriving}}
\typeset{do}{{\hs@keyface do}}
\typeset{else}{{\hs@keyface else}}
%\typeset{if}{{\hs@keyface if}}
\typeset{import}{{\hs@keyface import}}
\typeset{in}{$\in$}
\typeset{infix}{{\hs@keyface infix}}
\typeset{infixl}{{\hs@keyface infixl}}
\typeset{infixr}{{\hs@keyface infixr}}
\typeset{instance}{{\hs@keyface instance}}
\typeset{let}{{\hs@keyface let}}
\typeset{module}{{\hs@keyface module}}
\typeset{newtype}{{\hs@keyface newtype}}
\typeset{of}{{\hs@keyface of}}
\typeset{then}{{\hs@keyface then}}
\typeset{type}{{\hs@keyface type}}
\typeset{where}{{\hs@keyface where}}
\typeset{as}{{\hs@keyface as}}
\typeset{qualified}{{\hs@keyface qualified}}
\typeset{hiding}{{\hs@keyface hiding}}
\typeset{otherwise}{{\hs@keyface otherwise}}
\typeset{blw}{$\sqsubseteq$}
\typeset{abv}{$\sqsupseteq$}

\newlength{\spacewidth} % (added by florian).
\settowidth{\spacewidth}{ } % (added by florian).
\typeset{invfun}{$\hspace{-\spacewidth}^{-1}$} % (added by florian).
\typeset{relseqeq}{$\rightarrow^{\text{{\hs@sfunface seq}},=}$} % (added by florian).
\typeset{relseqineq}{$\rightarrow^{\text{{\hs@sfunface seq}},\sqsubseteq}$} % (added by florian).
\typeset{lift}{{\hs@conface lift}} % (added by florian).

%\typeset{xii}{\edef\hs@sub{j}\edef\hs@tok{x}\hs@emitvar}

% Define Greek letters:
\typeset{alpha}{$\alpha^{\hs@sup}_{\hs@sub}$}
\typeset{beta}{$\beta^{\hs@sup}_{\hs@sub}$}
\typeset{gamma}{$\gamma^{\hs@sup}_{\hs@sub}$}
\typeset{delta}{$\delta^{\hs@sup}_{\hs@sub}$}
\typeset{epsilon}{$\epsilon^{\hs@sup}_{\hs@sub}$}
\typeset{zeta}{$\zeta^{\hs@sup}_{\hs@sub}$}
\typeset{eta}{$\eta^{\hs@sup}_{\hs@sub}$}
\typeset{theta}{$\theta^{\hs@sup}_{\hs@sub}$}
\typeset{iota}{$\iota^{\hs@sup}_{\hs@sub}$}
\typeset{kappa}{$\kappa^{\hs@sup}_{\hs@sub}$}
\typeset{lambda}{$\lambda^{\hs@sup}_{\hs@sub}$}
\typeset{mu}{$\mu^{\hs@sup}_{\hs@sub}$}
\typeset{nu}{$\nu^{\hs@sup}_{\hs@sub}$}
\typeset{xi}{$\xi^{\hs@sup}_{\hs@sub}$}
\typeset{pi}{$\pi^{\hs@sup}_{\hs@sub}$}
\typeset{rho}{$\rho^{\hs@sup}_{\hs@sub}$}
\typeset{sigma}{$\sigma^{\hs@sup}_{\hs@sub}$}
\typeset{tau}{$\tau^{\hs@sup}_{\hs@sub}$}
\typeset{upsilon}{$\upsilon^{\hs@sup}_{\hs@sub}$}
\typeset{phi}{$\phi^{\hs@sup}_{\hs@sub}$}
\typeset{chi}{$\chi^{\hs@sup}_{\hs@sub}$}
\typeset{psi}{$\psi^{\hs@sup}_{\hs@sub}$}
\typeset{omega}{$\omega^{\hs@sup}_{\hs@sub}$}

\typeset{Alpha}{$\mit A^{\hs@sup}_{\hs@sub}$}
\typeset{Beta}{$\mit B^{\hs@sup}_{\hs@sub}$}
\typeset{Gamma}{$\mit\Gamma^{\hs@sup}_{\hs@sub}$}
\typeset{Delta}{$\mit\Delta^{\hs@sup}_{\hs@sub}$}
\typeset{Epsilon}{$\mit E^{\hs@sup}_{\hs@sub}$}
\typeset{Zeta}{$\mit Z^{\hs@sup}_{\hs@sub}$}
\typeset{Eta}{$\mit H^{\hs@sup}_{\hs@sub}$}
\typeset{Theta}{$\mit\Theta^{\hs@sup}_{\hs@sub}$}
\typeset{Iota}{$\mit I^{\hs@sup}_{\hs@sub}$}
\typeset{Kappa}{$\mit K^{\hs@sup}_{\hs@sub}$}
\typeset{Lambda}{$\mit\Lambda^{\hs@sup}_{\hs@sub}$}
\typeset{Mu}{$\mit M^{\hs@sup}_{\hs@sub}$}
\typeset{Nu}{$\mit N^{\hs@sup}_{\hs@sub}$}
\typeset{Xi}{$\mit\Xi^{\hs@sup}_{\hs@sub}$}
\typeset{Pi}{$\mit\Pi^{\hs@sup}_{\hs@sub}$}
\typeset{Rho}{$\mit P^{\hs@sup}_{\hs@sub}$}
\typeset{Sigma}{$\mit\Sigma^{\hs@sup}_{\hs@sub}$}
\typeset{Tau}{$\mit T^{\hs@sup}_{\hs@sub}$}
\typeset{Upsilon}{$\mit\Upsilon^{\hs@sup}_{\hs@sub}$}
\typeset{Phi}{$\mit\Phi^{\hs@sup}_{\hs@sub}$}
\typeset{Chi}{$\mit X^{\hs@sup}_{\hs@sub}$}
\typeset{Psi}{$\mit\Psi^{\hs@sup}_{\hs@sub}$}
\typeset{Omega}{$\mit\Omega^{\hs@sup}_{\hs@sub}$}

\typeset{ALPHA}{$\rm A^{\hs@sup}_{\hs@sub}$}
\typeset{BETA}{$\rm B^{\hs@sup}_{\hs@sub}$}
\typeset{GAMMA}{$\Gamma^{\hs@sup}_{\hs@sub}$}
\typeset{DELTA}{$\Delta^{\hs@sup}_{\hs@sub}$}
\typeset{EPSILON}{$\rm E^{\hs@sup}_{\hs@sub}$}
\typeset{ZETA}{$\rm Z^{\hs@sup}_{\hs@sub}$}
\typeset{ETA}{$\rm H^{\hs@sup}_{\hs@sub}$}
\typeset{THETA}{$\Theta^{\hs@sup}_{\hs@sub}$}
\typeset{IOTA}{$\rm I^{\hs@sup}_{\hs@sub}$}
\typeset{KAPPA}{$\rm K^{\hs@sup}_{\hs@sub}$}
\typeset{LAMBDA}{$\Lambda^{\hs@sup}_{\hs@sub}$}
\typeset{MU}{$\rm M^{\hs@sup}_{\hs@sub}$}
\typeset{NU}{$\rm N^{\hs@sup}_{\hs@sub}$}
\typeset{XI}{$\Xi^{\hs@sup}_{\hs@sub}$}
\typeset{PI}{$\Pi^{\hs@sup}_{\hs@sub}$}
\typeset{RHO}{$\rm P^{\hs@sup}_{\hs@sub}$}
\typeset{SIGMA}{$\Sigma^{\hs@sup}_{\hs@sub}$}
\typeset{TAU}{$\rm T^{\hs@sup}_{\hs@sub}$}
\typeset{UPSILON}{$\Upsilon^{\hs@sup}_{\hs@sub}$}
\typeset{PHI}{$\Phi^{\hs@sup}_{\hs@sub}$}
\typeset{CHI}{$\rm X^{\hs@sup}_{\hs@sub}$}
\typeset{PSI}{$\Psi^{\hs@sup}_{\hs@sub}$}
\typeset{OMEGA}{$\Omega^{\hs@sup}_{\hs@sub}$}

% Other math letters:
\typeset{aleph}{$\aleph$}
\typeset{infinity}{$\infty$}
\typeset{nabla}{$\nabla$}
\typeset{any}{$\exists$}
\typeset{all}{$\forall$}
\typeset{sum}{$\sum$}
\typeset{product}{$\prod$}
%\typeset{and}{$\bigwedge$}
\typeset{or}{$\bigvee$}
\typeset{undefined}{$\bot$}
\typeset{forall}{$\forall$}
\typeset{cup}{$\cup$}
\typeset{bigsqcup}{$\bigsqcup$}

% Define common symbols:
\typeset{=}{{\hs@symface=}}
\typeset{<-}{$\leftarrow$}
\typeset{->}{$\rightarrow$}
\typeset{=>}{$\Rightarrow$}
\typeset{++}{$+\kern-5pt+$}
\typeset{==}{$=$}
\typeset{/=}{${\mit/}\kern-.65em=$}
\typeset{<=}{$\leq$}
\typeset{>=}{$\geq$}
\typeset{||}{$\vee$}
\typeset{&&}{$\wedge$}
\typeset{==>}{$\Rightarrow$}
\typeset{<=>}{$\Leftrightarrow$}

% Symbols with a backslash are a little tricky:
{\catcode`/=0\catcode92=12
 /expandafter/xdef/csname<\>/endcsname{$/lambda$}}

% Define a space letter (used in a few places)
{\catcode32=12\gdef\hs@{ }}

% Prepare the character codes, etc for use in haskell mode:
\def\hs@preparecodemode{%
 \textfont15=\hs@symface
 \scriptfont15=\hs@ssymface
 \scriptscriptfont15=\hs@sssymface
 % Category codes:
 \chardef\hs@catcodeIX=\catcode9 \catcode9=12
 \chardef\hs@catcodeXIII=\catcode13 \catcode13=12
 \chardef\hs@catcodeXXXII=\catcode32 \catcode32=12
 \chardef\hs@catcodeXXXIII=\catcode33 \catcode33=12
 \chardef\hs@catcodeXXXIV=\catcode34 \catcode34=12
 \chardef\hs@catcodeXXXV=\catcode35 \catcode35=12
 \chardef\hs@catcodeXXXVI=\catcode36 \catcode36=12
 \chardef\hs@catcodeXXXVII=\catcode37 \catcode37=12
 \chardef\hs@catcodeXXXVIII=\catcode38 \catcode38=12
 \chardef\hs@catcodeXXXIX=\catcode39 \catcode39=12
 \chardef\hs@catcodeXL=\catcode40 \catcode40=12
 \chardef\hs@catcodeXLI=\catcode41 \catcode41=12
 \chardef\hs@catcodeXLII=\catcode42 \catcode42=12
 \chardef\hs@catcodeXLIII=\catcode43 \catcode43=12
 \chardef\hs@catcodeXLIV=\catcode44 \catcode44=12
 \chardef\hs@catcodeXLV=\catcode45 \catcode45=12
 \chardef\hs@catcodeXLVI=\catcode46 \catcode46=12
 \chardef\hs@catcodeXLVII=\catcode47 \catcode47=12
 \chardef\hs@catcodeLVIII=\catcode58 \catcode58=12
 \chardef\hs@catcodeLIX=\catcode59 \catcode59=12
 \chardef\hs@catcodeLX=\catcode60 \catcode60=12
 \chardef\hs@catcodeLXI=\catcode61 \catcode61=12
 \chardef\hs@catcodeLXII=\catcode62 \catcode62=12
 \chardef\hs@catcodeLXIII=\catcode63 \catcode63=12
 \chardef\hs@catcodeLXIV=\catcode64 \catcode64=12
 \chardef\hs@catcodeXCI=\catcode91 \catcode91=12
 \chardef\hs@catcodeXCII=\catcode92 \catcode92=12
 \chardef\hs@catcodeXCIII=\catcode93 \catcode93=12
 \chardef\hs@catcodeXCIV=\catcode94 \catcode94=12
 \chardef\hs@catcodeXCV=\catcode95 \catcode95=12
 \chardef\hs@catcodeXCVI=\catcode96 \catcode96=12
 \chardef\hs@catcodeCXXIII=\catcode123 \catcode123=12
 \chardef\hs@catcodeCXXIV=\catcode124 \catcode124=12
 \chardef\hs@catcodeCXXV=\catcode125 \catcode125=12
 \chardef\hs@catcodeCXXVI=\catcode126 \catcode126=12
 % Math codes for Haskell symbols:
 \mathchardef\hs@mathcodeXXXIII=\mathcode33 \mathcode33="0F21 % !
 \mathchardef\hs@mathcodeXXXV=\mathcode35 \mathcode35="0F23 % #
 \mathchardef\hs@mathcodeXXXVI=\mathcode36 \mathcode36="0F24 % $
 \mathchardef\hs@mathcodeXXXVII=\mathcode37 \mathcode37="0F25 % %
 \mathchardef\hs@mathcodeXXXVIII=\mathcode38 \mathcode38="0F26 % &
 \mathchardef\hs@mathcodeXL=\mathcode40 \mathcode41="0028 % (
 \mathchardef\hs@mathcodeXLI=\mathcode41 \mathcode41="0029 % )
 \mathchardef\hs@mathcodeXLII=\mathcode42 \mathcode42="0203 % *
 \mathchardef\hs@mathcodeXLIII=\mathcode43 \mathcode43="002B % +
 \mathchardef\hs@mathcodeXLIV=\mathcode44 \mathcode44="0F2C % ,
 \mathchardef\hs@mathcodeXLV=\mathcode45 \mathcode45="0200 % -
 \mathchardef\hs@mathcodeXLVI=\mathcode46 \mathcode46="0F2E % .
 \mathchardef\hs@mathcodeXLVII=\mathcode47 \mathcode47="002F % /
 \mathchardef\hs@mathcodeLVIII=\mathcode58 \mathcode58="003A % :
 \mathchardef\hs@mathcodeLVIX=\mathcode59 \mathcode59="0F3B % ;
 \mathchardef\hs@mathcodeLX=\mathcode60 \mathcode60="013C % <
 \mathchardef\hs@mathcodeLXI=\mathcode61 \mathcode61="003D % =
 \mathchardef\hs@mathcodeLXII=\mathcode62 \mathcode62="013E % >
 \mathchardef\hs@mathcodeLXIII=\mathcode63 \mathcode63="0F3F % ?
 \mathchardef\hs@mathcodeLXIV=\mathcode64 \mathcode64="0F40 % @
 \mathchardef\hs@mathcodeXCI=\mathcode91 \mathcode91="005B % [
 \mathchardef\hs@mathcodeXCII=\mathcode92 \mathcode92="026E % \
 \mathchardef\hs@mathcodeXCIII=\mathcode93 \mathcode93="005D % ]
 \mathchardef\hs@mathcodeXCVI=\mathcode96 \mathcode96="0012 % `
 \mathchardef\hs@mathcodeCXXIII=\mathcode123 \mathcode123="0266 % {
 \mathchardef\hs@mathcodeCXXIV=\mathcode124 \mathcode124="007C % |
 \mathchardef\hs@mathcodeCXXV=\mathcode125 \mathcode125="0267 % {
 \mathchardef\hs@mathcodeCXXVI=\mathcode126 \mathcode126="0F7E % ~
 \relax}

% Restore "normal" TeX environment within haskell comments:
\def\hs@preparecommentmode{%
 % Category codes:
 \catcode9=\hs@catcodeIX
 \catcode13=\hs@catcodeXIII
 \catcode32=\hs@catcodeXXXII
 \catcode33=\hs@catcodeXXXIII
 \catcode34=\hs@catcodeXXXIV
 \catcode35=\hs@catcodeXXXV
 \catcode36=\hs@catcodeXXXVI
 \catcode37=\hs@catcodeXXXVII
 \catcode38=\hs@catcodeXXXVIII
 \catcode39=\hs@catcodeXXXIX
 \catcode40=\hs@catcodeXL
 \catcode41=\hs@catcodeXLI
 \catcode42=\hs@catcodeXLII
 \catcode43=\hs@catcodeXLIII
 \catcode44=\hs@catcodeXLIV
 \catcode45=\hs@catcodeXLV
 \catcode46=\hs@catcodeXLVI
 \catcode47=\hs@catcodeXLVII
 \catcode58=\hs@catcodeLVIII
 \catcode59=\hs@catcodeLIX
 \catcode60=\hs@catcodeLX
 \catcode61=\hs@catcodeLXI
 \catcode62=\hs@catcodeLXII
 \catcode63=\hs@catcodeLXIII
 \catcode64=\hs@catcodeLXIV
 \catcode91=\hs@catcodeXCI
 \catcode92=\hs@catcodeXCII
 \catcode93=\hs@catcodeXCIII
 \catcode94=\hs@catcodeXCIV
 \catcode95=\hs@catcodeXCV
 \catcode96=\hs@catcodeXCVI
 \catcode123=\hs@catcodeCXXIII
 \catcode124=\hs@catcodeCXXIV
 \catcode125=\hs@catcodeCXXV
 \catcode126=\hs@catcodeCXXVI
 % Math codes for Haskell symbols:
 \mathcode33=\hs@mathcodeXXXIII % !
 \mathcode35=\hs@mathcodeXXXV % #
 \mathcode36=\hs@mathcodeXXXVI % $
 \mathcode37=\hs@mathcodeXXXVII % %
 \mathcode38=\hs@mathcodeXXXVIII % &
 \mathcode40=\hs@mathcodeXL % (
 \mathcode41=\hs@mathcodeXLI % )
 \mathcode42=\hs@mathcodeXLII % *
 \mathcode43=\hs@mathcodeXLIII % +
 \mathcode44=\hs@mathcodeXLIV % ,
 \mathcode45=\hs@mathcodeXLV % -
 \mathcode46=\hs@mathcodeXLVI % .
 \mathcode47=\hs@mathcodeXLVII % /
 \mathcode58=\hs@mathcodeLVIII % :
 \mathcode59=\hs@mathcodeLVIX % ;
 \mathcode60=\hs@mathcodeLX % <
 \mathcode61=\hs@mathcodeLXI % =
 \mathcode62=\hs@mathcodeLXII % >
 \mathcode63=\hs@mathcodeLXIII % ?
 \mathcode64=\hs@mathcodeLXIV % @
 \mathcode91=\hs@mathcodeXCI % [
 \mathcode92=\hs@mathcodeXCII % \
 \mathcode93=\hs@mathcodeXCIII % ]
 \mathcode96=\hs@mathcodeXCVI % `
 \mathcode123=\hs@mathcodeCXXIII % {
 \mathcode124=\hs@mathcodeCXXIV % |
 \mathcode125=\hs@mathcodeCXXV % {
 \mathcode126=\hs@mathcodeCXXVI % ~
 \relax}

% Entry points for each of the three modes:
\def\hs@preparehaskell{%
 % Initial token "registers":
 \xdef\hs@tok{}\edef\hs@sup{}\edef\hs@sub{}\hs@space=0pt
 \hs@preparecodemode}

\def\hs@beginInline{%
 \begingroup
 \hs@inlinetrue
 \everyhs
 \hs@preparehaskell\hs@lex@state}
\def\hs@endInline{%
 \endgroup}

\def\hs@beginBird{%
 \beforehs
 \begingroup
 \hs@inlinefalse
 \everyhs
 \offinterlineskip
 \def\hs@parskip{}%
 \hs@preparehaskell
 \hs@previndent=0pt
 \hs@indent=\hsleftskip
 \hs@code@state}

% Entry point for the italic mode:
{\catcode`>=\active
 \gdef\hs@beginitalic{\begingroup\it\catcode`>=\active\let>=\endgroup}}

% Lexeme formatting macros:
\def\hs@emitvar{%
 \if\csname<\hs@tok>\endcsname\relax
  \setbox255=\hbox{\hs@varface\hs@tok\/$^{\hs@sup}_{\hs@sub}$}%
 \else
  \setbox255=\hbox{\csname<\hs@tok>\endcsname}%
 \fi
 \hs@emit}

\def\hs@emitcon{%
 \if\csname<\hs@tok>\endcsname\relax
  \setbox255=\hbox{\hs@conface\hs@tok$^{\hs@sup}_{\hs@sub}$}%
 \else
  \setbox255=\hbox{\csname<\hs@tok>\endcsname}%
 \fi
 \hs@emit}

\def\hs@emitsym{%
 \def\hs@guard{|}%
 \ifx\hs@tok\hs@guard
  \ifhs@inline
   \kern\hs@space\hbox{$|$}%
  \else
   \ifhbox\hs@i
    % Set the new guard position:
    \hs@guardpos=\hs@indent
    \advance\hs@guardpos by \wd\hs@i
    \advance\hs@guardpos by \hs@space
   \else
    % Align the guard with the previous one:
    \ifdim\hs@guardpos>0pt\hs@indent=\hs@guardpos\fi
   \fi
   \global\setbox\hs@i=\hbox{%
    \ifhbox\hs@i\unhbox\hs@i\fi\kern\hs@space\vrule width.17pt\ }%
   \hs@afteremit
  \fi
 \else
  \if\csname<\hs@tok>\endcsname\relax
   \setbox255=\hbox{$\hs@tok$}%
  \else
   \setbox255=\hbox{\csname<\hs@tok>\endcsname}%
  \fi
  \hs@emit
 \fi}

\def\hs@emitnum#1{%
 \if\csname<#1\hs@tok>\endcsname\relax
  \setbox255=\hbox{\hs@numface\hs@tok$_{\hs@sub}$}%
 \else
  \setbox255=\hbox{\csname<#1\hs@tok>\endcsname}%
 \fi
 \hs@emit}

\def\hs@emitchr{%
 \if\csname<\hs@tok>\endcsname\relax
  \setbox255=\hbox{\hs@symface`{\hs@strface\hs@tok}'}%
 \else
  \setbox255=\hbox{\csname<\hs@tok>\endcsname}%
 \fi
 \hs@emit}

\def\hs@emit{%
 \ifhs@inline
  \kern\hs@space\box255
 \else
  \global\setbox\hs@i=\hbox{\ifhbox\hs@i\unhbox\hs@i\fi\kern\hs@space\box255}%
 \fi
 \hs@afteremit}
\def\hs@afteremit{%
 \xdef\hs@tok{}\edef\hs@sup{}\edef\hs@sub{}\hs@space=0pt}

\def\hs@outputline{%
 \ifhbox\hs@i
  % Emit the previous line:
  \dimen255=\hsize
  \advance\dimen255 by -\hsrightskip
  \ifdim\wd\hs@i>\dimen255
   \dimen255=-\dimen255 \advance\dimen255 by \wd\hs@i
   \count255=\inputlineno \advance\count255 by -1
   \immediate\write16{}%
   \immediate\write16{%
    Overful \hbox (\the\dimen255\hs@ too wide)
    in Haskell code at line \the\count255}%
   \global\setbox\hs@i=\hbox{\unhbox\hs@i\vrule width\overfullrule}%
  \fi
  \hs@parskip
  \hbox{\strut\kern\hs@indent\unhbox\hs@i}%
  % Reset the guard position if necessary:
  \ifdim\hs@indent>\hs@previndent\else
   \hs@guardpos=0pt
  \fi
  % Update indentation levels:
  \hs@previndent=\hs@indent
  \hs@indent=\hsleftskip
 \fi}

% Entry point for the comment mode:
\def\hs@emitdashes{%
 \setbox255=\hbox{\hskip\hscommentskip\hs@symface---\hs@tok}\hs@emit}
\def\hs@preparecomment{%
 \hs@emitdashes
 \begingroup
 \hs@preparecommentmode
 \catcode13=12
 \relax}
{\catcode13=12\gdef\hs@comment@state#1^^M{\hs@emitcomment{#1}}}
\def\hs@emitcomment#1{%
 \endgroup
 \ifhs@inline
  \errmessage{Comment in inline Haskell mode}%
 \else
  \setbox255=\hbox{#1\hfill}\hs@emit
  \let\next=\hs@newline@state
 \fi
 \next}

% \endgroup
% \begingroup
% \hs@inlinefalse
% \everyhs
% \offinterlineskip
% \def\hs@parskip{}%
% \hs@preparehaskell
% \hs@previndent=0pt
% \hs@indent=\hsleftskip
% \hs@newline@state}

%%% Function detection %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% Haskell syntax does not distinguish between functions and variables, but
% we would like to typeset each kind of names differently. Therefore, I
% define a convinient \functions macro which accepts a comma-separated list
% of function names. To change a function back into a variable, prefix its
% name in the list with the ! character.

\def\functions(#1){\def\hs@tok{}\hs@funbegin#1\relax}
\def\hs@funbegin#1{%
 \ifx#1\relax
  \let\next=\relax
 \else\ifx#1,
  \let\next=\hs@funbegin
 \else\ifnum`#1=9
  \let\next=\hs@funbegin
 \else\ifnum`#1=32
  \let\next=\hs@funbegin
 \else\if#1!
  \xdef\hs@tok{}%
  \let\next=\hs@varcollect
 \else 
  \xdef\hs@tok{#1}%
  \let\next=\hs@funcollect
 \fi\fi\fi\fi\fi
 \next}
\def\hs@funcollect#1{%
 \ifx#1\relax
  \typeset{\hs@tok}{{\hs@funface\hs@tok$^{\hs@sup}_{\hs@sub}$}}%
  \let\next=\relax
 \else\ifx#1,
  \typeset{\hs@tok}{{\hs@funface\hs@tok$^{\hs@sup}_{\hs@sub}$}}%
  \let\next=\hs@funbegin
 \else\ifnum`#1=9
  \typeset{\hs@tok}{{\hs@funface\hs@tok$^{\hs@sup}_{\hs@sub}$}}%
  \let\next=\hs@funbegin
 \else\ifnum`#1=32
  \typeset{\hs@tok}{{\hs@funface\hs@tok$^{\hs@sup}_{\hs@sub}$}}%
  \let\next=\hs@funbegin
 \else 
  \xdef\hs@tok{\hs@tok#1}%
  \let\next=\hs@funcollect
 \fi\fi\fi\fi
 \next}
\def\hs@varcollect#1{%
 \ifx#1\relax
  \typeset{\hs@tok}{{\hs@varface\hs@tok$^{\hs@sup}_{\hs@sub}$}}%
  \let\next=\relax
 \else\ifx#1,
  \typeset{\hs@tok}{{\hs@varface\hs@tok$^{\hs@sup}_{\hs@sub}$}}%
  \let\next=\hs@funbegin
 \else\ifnum`#1=9
  \typeset{\hs@tok}{{\hs@varface\hs@tok$^{\hs@sup}_{\hs@sub}$}}%
  \let\next=\hs@funbegin
 \else\ifnum`#1=32
  \typeset{\hs@tok}{{\hs@varface\hs@tok$^{\hs@sup}_{\hs@sub}$}}%
  \let\next=\hs@funbegin
 \else 
  \xdef\hs@tok{\hs@tok#1}%
  \let\next=\hs@varcollect
 \fi\fi\fi\fi
 \next}

% Define standard prelude functions:
% Prelude:
\functions (succ,pred,toEnum,fromEnum,enumFrom,enumFromThen,enumFromTo,
 enumFromThenTo,minBound,maxBound,negate,abs,signum,fromInteger,toRational,
 quot,rem,div,mod,quotRem,divMod,toInteger,recip,fromRational,exp,log,sqrt,
 logBase,sin,cos,tan,asin,acos,atan,sinh,cosh,tanh,asinh,acosh,atanh,
 properFraction,truncate,round,ceiling,floor,floatRadix,floatDigits,floatRange,
 decodeFloat,encodeFloat,exponent,significand,scaleFloat,isNaN,isInfinite,
 isDenormalized,isIEEE,isNegativeZero,atan2,return,fail,fmap,mapM,
 sequence,maybe,either,not,otherwise,subtract,even,odd,gcd,lcm,
 fromIntegral,realToFrac,fst,snd,curry,uncurry,id,const,flip,until,
 asTypeOf,error,seq)
% PreludeList:
\functions (map,filter,concat,head,last,tail,init,null,length,foldl,scanl,
 foldr,scanr,iterate,repeat,replicate,cycle,take,drop,splitAt,takeWhile,
 dropWhile,span,break,lines,words,unlines,unwords,reverse,elem,notElem,lookup,
 maximum,minimum,concatMap,zip,zipWith,unzip)
% PreludeText:
\functions (readsProc,readList,showsProc,showList,reads,shows,show,read,lex,
 showChar,showString,readParen,showParen)
% PreludeIO:
\functions (ioError,userError,catch,putChar,putStr,putStrLn,print,getChar,
 getLine,getContents,interact,readFile,writeFile,appendFile,readIO,readLn)
% other typeclass-methods:
\functions (compare, showsPrec, readsPrec, mempty, mappend, mconcat)


%%% Haskell category codes %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% In a moment we will implement a relatively complete lexical analyser for
% Haskell. To make our job simpler, we collect all ASCII characters into
% the following ten equivalence classes:
%
%       0. SP - space
%       1. LC - lowercase letters
%       2. UC - uppercase letters
%       3. DI - digits
%       4. SY - symbols
%       5. PU - punctuators
%       6. AP - apostrophe
%       7. QT - double quotation mark
%       8. NL - newline

\chardef\hs@SP=0
\chardef\hs@LC=1
\chardef\hs@UC=2
\chardef\hs@DI=3
\chardef\hs@SY=4
\chardef\hs@PU=5
\chardef\hs@AP=6
\chardef\hs@QT=7
\chardef\hs@NL=8

% The macro \hs@getcc#1 computes the Haskell category code of its argument
% ans stores it in the counter variable \hs@cc.

\newcount\hs@cc
\def\hs@getcc#1{%
  \hs@cc=`#1
  \ifnum\hs@cc<65 %%% NUL - @
    \ifnum\hs@cc<32 %%% NUL - US
     \ifnum\hs@cc=9
       \hs@cc=\hs@SP
     \else\ifnum\hs@cc=13
       \hs@cc=\hs@NL
     \else
       \hs@cc=-1
     \fi\fi
    \else %%% SP - @
     \ifnum\hs@cc<48 %%% SP - /
       \ifnum\hs@cc=32 %%% SP
         \hs@cc=\hs@SP
       \else\ifnum\hs@cc=34 %%% "
         \hs@cc=\hs@QT
       \else\ifnum\hs@cc=39 %%% '
         \hs@cc=\hs@AP
       \else\ifnum\hs@cc=40 %%% (
         \hs@cc=\hs@PU
       \else\ifnum\hs@cc=41 %%% )
         \hs@cc=\hs@PU
       \else\ifnum\hs@cc=44 %%% ,
         \hs@cc=\hs@PU
       \else
         \hs@cc=\hs@SY
       \fi\fi\fi\fi\fi\fi
     \else %%% 0 - @
       \ifnum\hs@cc<58 %%% 0 - 9
         \hs@cc=\hs@DI
       \else\ifnum\hs@cc=59 %%% ;
         \hs@cc=\hs@PU
       \else
         \hs@cc=\hs@SY
       \fi\fi
     \fi
    \fi      
  \else %%% A - DEL
    \ifnum\hs@cc<97 %%% A - `
      \ifnum\hs@cc<91 %%% A - Z
        \hs@cc=\hs@UC
      \else\ifnum\hs@cc=92 %%% \
        \hs@cc=\hs@SY
      \else\ifnum\hs@cc=94 %%% ^
        \hs@cc=\hs@SY
      % \else\ifnum\hs@cc=95 %%% _
      %  \hs@cc=\hs@LC
      \else %%% [ ] `
        \hs@cc=\hs@PU
      \fi\fi\fi%\fi
    \else %%% a - DEL
      \ifnum\hs@cc<123 %%% a - z
        \hs@cc=\hs@LC
      \else\ifnum\hs@cc=123 %%% {
        \hs@cc=\hs@PU
      \else\ifnum\hs@cc=124 %%% |
        \hs@cc=\hs@SY
      \else\ifnum\hs@cc=125 %%% }
        \hs@cc=\hs@PU
      \else\ifnum\hs@cc=126 %%% ~
        \hs@cc=\hs@SY
      \else
        \hs@cc=-1
      \fi\fi\fi\fi\fi
    \fi
  \fi}

%%% The lexical analyzer %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% Now we are ready to implement the actual lexical analyzer.
%

\def\hs@code@state#1{%
 \hs@getcc#1%
 \ifcase\hs@cc
        % SP - space
        \ifnum`#1=9\advance\hs@indent by \hstabwidth
        \else\advance\hs@indent by \hsspacewidth\fi
        \let\next=\hs@code@state
   \or  % LC - lowercase letters
        \xdef\hs@tok{#1}%
        \let\next=\hs@var@state
   \or  % UC - uppercase letters
        \xdef\hs@tok{#1}%
        \let\next=\hs@con@state
   \or  % DI - digits
        \xdef\hs@tok{#1}%
        \ifx#10\let\next=\hs@zero@state\else\let\next=\hs@dec@state\fi
   \or  % SY - symbols
        \xdef\hs@tok{#1}%
        \ifx#1-\let\next=\hs@dash@state\else\let\next=\hs@sym@state\fi
   \or  % PU - punctuators
        \xdef\hs@tok{#1}%
        \hs@emitsym
        \let\next=\hs@lex@state
   \or  % AP - apostrophe
        \let\next=\hs@chr@state
   \or  % QT - double quotation mark
        \let\next=\hs@str@state
   \or  % NL - newline
        \def\hs@parskip{\vskip\hsparskip\def\hs@parskip{}}%
        \let\next=\hs@newline@state
   \else
        \errmessage{Illegal character in Haskell mode: #1}%
 \fi
 \next}

\def\hs@newline@state#1{%
 \hs@outputline
 \ifx#1>
  \hs@space=0pt
  \let\next=\hs@code@state
 \else
  % It must be a space or a newline; just drop it.
  \par
  \endgroup
  \afterhs
  \par\noindent\ignorespaces
  \let\next=\relax
 \fi
 \next}

\def\hs@lex@state#1{%
 \hs@getcc#1%
 \ifcase\hs@cc
        % SP - space
        \hs@space=\hswordspace
        \let\next=\hs@lex@state
   \or  % LC - lowercase letters
        \xdef\hs@tok{#1}%
        \let\next=\hs@var@state
   \or  % UC - uppercase letters
        \xdef\hs@tok{#1}%
        \let\next=\hs@con@state
   \or  % DI - digits
        \xdef\hs@tok{#1}%
        \ifx#10\let\next=\hs@zero@state\else\let\next=\hs@dec@state\fi
   \or  % SY - symbols
        \xdef\hs@tok{#1}%
        \ifx#1-\let\next=\hs@dash@state\else\let\next=\hs@sym@state\fi
   \or  % PU - punctuators
        \xdef\hs@tok{#1}%
        \hs@emitsym
        \let\next=\hs@lex@state
   \or  % AP - apostrophe
        \xdef\hs@tok{}%
        \let\next=\hs@chr@state
   \or  % QT - double quotation mark
        \ifhs@inline
         \hs@endInline
         \let\next=\relax
        \else
         \xdef\hs@tok{}%
         \let\next=\hs@str@state
        \fi
   \or  % NL - newline
        \ifhs@inline
         \hs@space=\hswordspace
         \let\next=\hs@lex@state
        \else
         \let\next=\hs@newline@state
        \fi
   \else
        \errmessage{Illegal character in Haskell mode: #1}%
 \fi
 \next}

\def\hs@var@state#1{%
 \hs@getcc#1%
 \ifcase\hs@cc
        % SP - space
        \hs@emitvar
        \hs@space=\hswordspace
        \let\next=\hs@lex@state
   \or  % LC - lowercase letters
        \xdef\hs@tok{\hs@tok#1}%
        \let\next=\hs@var@state
   \or  % UC - uppercase letters
        \xdef\hs@tok{\hs@tok#1}%
        \let\next=\hs@var@state
   \or  % DI - digits
        \edef\hs@sub{\hs@sub#1}%
        \let\next=\hs@var@state
   \or  % SY - symbols
        \hs@emitvar
        \xdef\hs@tok{#1}%
        \ifx#1-\let\next=\hs@dash@state\else\let\next=\hs@sym@state\fi
   \or  % PU - punctuators
        \hs@emitvar
        \xdef\hs@tok{#1}%
        \hs@emitsym
        \let\next=\hs@lex@state
   \or  % AP - apostrophe
        \edef\hs@sup{\hs@sup\prime}%
        \let\next=\hs@var@state
   \or  % QT - double quotation mark
        \hs@emitvar
        \ifhs@inline
         \hs@endInline
         \let\next=\relax
        \else
         \let\next=\hs@str@state
        \fi
   \or  % NL - newline
        \hs@emitvar
        \ifhs@inline
         \hs@space=\hswordspace
         \let\next=\hs@lex@state
        \else
         \let\next=\hs@newline@state
        \fi
   \else
        \errmessage{Illegal character in Haskell mode: #1}%
 \fi
 \next}
        
\def\hs@con@state#1{%
 \hs@getcc#1%
 \ifcase\hs@cc
        % SP - space
        \hs@emitcon
        \hs@space=\hswordspace
        \let\next=\hs@lex@state
   \or  % LC - lowercase letters
        \xdef\hs@tok{\hs@tok#1}%
        \let\next=\hs@con@state
   \or  % UC - uppercase letters
        \xdef\hs@tok{\hs@tok#1}%
        \let\next=\hs@con@state
   \or  % DI - digits
        \edef\hs@sub{\hs@sub#1}%
        \let\next=\hs@con@state
   \or  % SY - symbols
        \hs@emitcon
        \xdef\hs@tok{#1}%
        \ifx#1-\let\next=\hs@dash@state\else\let\next=\hs@sym@state\fi
   \or  % PU - punctuators
        \hs@emitcon
        \xdef\hs@tok{#1}%
        \hs@emitsym
        \let\next=\hs@lex@state
   \or  % AP - apostrophe
        \edef\hs@sup{\hs@sup\prime}%
        \let\next=\hs@con@state
   \or  % QT - double quotation mark
        \hs@emitcon
        \ifhs@inline
         \hs@endInline
         \let\next=\relax
        \else
         \let\next=\hs@str@state
        \fi
   \or  % NL - newline
        \hs@emitcon
        \ifhs@inline
         \hs@space=\hswordspace
         \let\next=\hs@lex@state
        \else
         \let\next=\hs@newline@state
        \fi
   \else
        \errmessage{Illegal character in Haskell mode: #1}%
 \fi
 \next}
        
\def\hs@sym@state#1{%
 \hs@getcc#1%
 \ifcase\hs@cc
        % SP - space
        \hs@emitsym
        \hs@space=\hswordspace
        \let\next=\hs@lex@state
   \or  % LC - lowercase letters
        \hs@emitsym
        \xdef\hs@tok{#1}%
        \let\next=\hs@var@state
   \or  % UC - uppercase letters
        \hs@emitsym
        \xdef\hs@tok{#1}%
        \let\next=\hs@con@state
   \or  % DI - digits
        \hs@emitsym
        \xdef\hs@tok{#1}%
        \ifx#10\let\next=\hs@zero@state\else\let\next=\hs@dec@state\fi
   \or  % SY - symbols
        \xdef\hs@tok{\hs@tok#1}%
        \let\next=\hs@sym@state
   \or  % PU - punctuators
        \hs@emitsym
        \xdef\hs@tok{#1}%
        \hs@emitsym
        \let\next=\hs@lex@state
   \or  % AP - apostrophe
        \hs@emitsym
        \xdef\hs@tok{}%
        \let\next=\hs@chr@state
   \or  % QT - double quotation mark
        \hs@emitsym
        \ifhs@inline
         \hs@endInline
         \let\next=\relax
        \else
         \xdef\hs@tok{}%
         \let\next=\hs@str@state
        \fi
   \or  % NL - newline
        \hs@emitsym
        \ifhs@inline
         \hs@space=\hswordspace
         \let\next=\hs@lex@state
        \else
         \let\next=\hs@newline@state
        \fi
   \else
        \errmessage{Illegal character in Haskell mode: #1}%
 \fi
 \next}

\def\hs@dash@state#1{%
 \hs@getcc#1%
 \ifcase\hs@cc
        % SP - space
        \hs@emitsym
        \hs@space=\hswordspace
        \let\next=\hs@lex@state
   \or  % LC - lowercase letters
        \hs@emitsym
        \xdef\hs@tok{#1}%
        \let\next=\hs@var@state
   \or  % UC - uppercase letters
        \hs@emitsym
        \xdef\hs@tok{#1}%
        \let\next=\hs@con@state
   \or  % DI - digits
        \hs@emitsym
        \xdef\hs@tok{#1}%
        \ifx#10\let\next=\hs@zero@state\else\let\next=\hs@dec@state\fi
   \or  % SY - symbols
        \xdef\hs@tok{\hs@tok#1}%
        \ifx#1-\let\next=\hs@dashdash@state\else\let\next=\hs@sym@state\fi
   \or  % PU - punctuators
        \hs@emitsym
        \xdef\hs@tok{#1}%
        \hs@emitsym
        \let\next=\hs@lex@state
   \or  % AP - apostrophe
        \hs@emitsym
        \xdef\hs@tok{}%
        \let\next=\hs@chr@state
   \or  % QT - double quotation mark
        \hs@emitsym
        \ifhs@inline
         \hs@endInline
         \let\next=\relax
        \else
         \xdef\hs@tok{}%
         \let\next=\hs@str@state
        \fi
   \or  % NL - newline
        \hs@emitsym
        \ifhs@inline
         \hs@space=\hswordspace
         \let\next=\hs@lex@state
        \else
         \let\next=\hs@newline@state
        \fi
   \else
        \errmessage{Illegal character in Haskell mode: #1}%
 \fi
 \next}

%%% XXX
\def\hs@dashdash@state#1{%
 \hs@getcc#1%
 \ifcase\hs@cc
        % SP - space
        \xdef\hs@tok{\hs@}%
        \hs@preparecomment
        \let\next=\hs@comment@state
   \or  % LC - lowercase letters
        \xdef\hs@tok{#1}%
        \hs@preparecomment
        \let\next=\hs@comment@state
   \or  % UC - uppercase letters
        \xdef\hs@tok{#1}%
        \hs@preparecomment
        \let\next=\hs@comment@state
   \or  % DI - digits
        \xdef\hs@tok{#1}%
        \hs@preparecomment
        \let\next=\hs@comment@state
   \or  % SY - symbols
        \xdef\hs@tok{\hs@tok#1}%
        \ifx#1-\let\next=\hs@dashdash@state\else\let\next=\hs@sym@state\fi
   \or  % PU - punctuators
        \xdef\hs@tok{#1}%
        \hs@preparecomment
        \let\next=\hs@comment@state
   \or  % AP - apostrophe
        \xdef\hs@tok{#1}%
        \hs@preparecomment
        \let\next=\hs@comment@state
   \or  % QT - double quotation mark
        \xdef\hs@tok{#1}%
        \hs@preparecomment
        \let\next=\hs@comment@state
   \or  % NL - newline
        \ifhs@inline
         \errmessage{Comment in inline Haskell mode}%
        \else
         \xdef\hs@tok{}%
         \hs@emitdashes
         \let\next=\hs@newline@state
        \fi
   \else
        \errmessage{Illegal character in Haskell mode: #1}%
 \fi
 \next}

\def\hs@zero@state#1{%
 \hs@getcc#1%
 \ifcase\hs@cc
        % SP - space
        \hs@emitnum{}%
        \hs@space=\hswordspace
        \let\next=\hs@lex@state
   \or  % LC - lowercase letters
        \ifx#1o
         \edef\hs@sub{8}%
         \xdef\hs@tok{}%
         \let\next=\hs@oct@state
        \else\ifx#1x
         \edef\hs@sub{16}%
         \xdef\hs@tok{}%
         \let\next=\hs@hex@state
        \else
         \hs@emitnum{}%
         \xdef\hs@tok{#1}%
         \let\next=\hs@var@state
        \fi\fi
   \or  % UC - uppercase letters
        \ifx#1O
         \edef\hs@sub{8}%
         \xdef\hs@tok{}%
         \let\next=\hs@oct@state
        \else\ifx#1X
         \edef\hs@sub{16}%
         \xdef\hs@tok{}%
         \let\next=\hs@hex@state
        \else
         \hs@emitnum{}%
         \xdef\hs@tok{#1}%
         \let\next=\hs@con@state
        \fi\fi
   \or  % DI - digits
        \xdef\hs@tok{\hs@tok#1}%
        \let\next=\hs@dec@state
   \or  % SY - symbols
        \hs@emitnum{}%
        \xdef\hs@tok{#1}%
        \ifx#1-\let\next=\hs@dash@state\else\let\next=\hs@sym@state\fi
   \or  % PU - punctuators
        \hs@emitnum{}%
        \xdef\hs@tok{#1}%
        \hs@emitsym
        \let\next=\hs@lex@state
   \or  % AP - apostrophe
        \hs@emitnum{}%
        \xdef\hs@tok{}%
        \let\next=\hs@chr@state
   \or  % QT - double quotation mark
        \hs@emitnum{}%
        \ifhs@inline
         \hs@endInline
         \let\next=\relax
        \else
         \xdef\hs@tok{}%
         \let\next=\hs@str@state
        \fi
   \or  % NL - newline
        \hs@emitnum{}%
        \ifhs@inline
         \hs@space=\hswordspace
         \let\next=\hs@lex@state
        \else
         \let\next=\hs@newline@state
        \fi
   \else
        \errmessage{Illegal character in Haskell mode: #1}%
 \fi
 \next}

\def\hs@dec@state#1{%
 \hs@getcc#1%
 \ifcase\hs@cc
        % SP - space
        \hs@emitnum{}%
        \hs@space=\hswordspace
        \let\next=\hs@lex@state
   \or  % LC - lowercase letters
        \hs@emitnum{}%
        \xdef\hs@tok{#1}%
        \let\next=\hs@var@state
   \or  % UC - uppercase letters
        \hs@emitnum{}%
        \xdef\hs@tok{#1}%
        \let\next=\hs@con@state
   \or  % DI - digits
        \xdef\hs@tok{\hs@tok#1}%
        \let\next=\hs@dec@state
   \or  % SY - symbols
        \hs@emitnum{}%
        \xdef\hs@tok{#1}%
        \ifx#1-\let\next=\hs@dash@state\else\let\next=\hs@sym@state\fi
   \or  % PU - punctuators
        \hs@emitnum{}%
        \xdef\hs@tok{#1}%
        \hs@emitsym
        \let\next=\hs@lex@state
   \or  % AP - apostrophe
        \hs@emitnum{}%
        \xdef\hs@tok{}%
        \let\next=\hs@chr@state
   \or  % QT - double quotation mark
        \hs@emitnum{}%
        \ifhs@inline
         \hs@endInline
         \let\next=\relax
        \else
         \xdef\hs@tok{}%
         \let\next=\hs@str@state
        \fi
   \or  % NL - newline
        \hs@emitnum{}%
        \ifhs@inline
         \hs@space=\hswordspace
         \let\next=\hs@lex@state
        \else
         \let\next=\hs@newline@state
        \fi
   \else
        \errmessage{Illegal character in Haskell mode: #1}%
 \fi
 \next}

\def\hs@oct@state#1{%
 \hs@getcc#1%
 \ifcase\hs@cc
        % SP - space
        \hs@emitnum{0o}%
        \hs@space=\hswordspace
        \let\next=\hs@lex@state
   \or  % LC - lowercase letters
        \hs@emitnum{0o}%
        \xdef\hs@tok{#1}%
        \let\next=\hs@var@state
   \or  % UC - uppercase letters
        \hs@emitnum{0o}%
        \xdef\hs@tok{#1}%
        \let\next=\hs@con@state
   \or  % DI - digits
        \ifnum`#1<`8
         \xdef\hs@tok{\hs@tok#1}%
         \let\next=\hs@oct@state
        \else
         \hs@emitnum{0o}%
         \xdef\hs@tok{#1}%
         \let\next=\hs@dec@state
        \fi
   \or  % SY - symbols
        \hs@emitnum{0o}%
        \xdef\hs@tok{#1}%
        \ifx#1-\let\next=\hs@dash@state\else\let\next=\hs@sym@state\fi
   \or  % PU - punctuators
        \hs@emitnum{0o}%
        \xdef\hs@tok{#1}%
        \hs@emitsym
        \let\next=\hs@lex@state
   \or  % AP - apostrophe
        \hs@emitnum{0o}%
        \xdef\hs@tok{}%
        \let\next=\hs@chr@state
   \or  % QT - double quotation mark
        \hs@emitnum{0o}%
        \ifhs@inline
         \hs@endInline
         \let\next=\relax
        \else
         \xdef\hs@tok{}%
         \let\next=\hs@str@state
        \fi
   \or  % NL - newline
        \hs@emitnum{0o}%
        \ifhs@inline
         \hs@space=\hswordspace
         \let\next=\hs@lex@state
        \else
         \let\next=\hs@newline@state
        \fi
   \else
        \errmessage{Illegal character in Haskell mode: #1}%
 \fi
 \next}

\def\hs@hex@state#1{%
 \hs@getcc#1%
 \ifcase\hs@cc
        % SP - space
        \hs@emitnum{0x}%
        \hs@space=\hswordspace
        \let\next=\hs@lex@state
   \or  % LC - lowercase letters
        \ifnum`#1<`g
         \xdef\hs@tok{\hs@tok#1}%
         \let\next=\hs@hex@state
        \else
         \hs@emitnum{0x}%
         \xdef\hs@tok{#1}%
         \let\next=\hs@var@state
        \fi
   \or  % UC - uppercase letters
        \ifnum`#1<`G
         \xdef\hs@tok{\hs@tok#1}%
         \let\next=\hs@hex@state
        \else
         \hs@emitnum{0x}%
         \xdef\hs@tok{#1}%
         \let\next=\hs@con@state
        \fi
   \or  % DI - digits
        \xdef\hs@tok{\hs@tok#1}%
        \let\next=\hs@hex@state
   \or  % SY - symbols
        \hs@emitnum{0x}%
        \xdef\hs@tok{#1}%
        \ifx#1-\let\next=\hs@dash@state\else\let\next=\hs@sym@state\fi
   \or  % PU - punctuators
        \hs@emitnum{0x}%
        \xdef\hs@tok{#1}%
        \hs@emitsym
        \let\next=\hs@lex@state
   \or  % AP - apostrophe
        \hs@emitnum{0x}%
        \xdef\hs@tok{}%
        \let\next=\hs@chr@state
   \or  % QT - double quotation mark
        \hs@emitnum{0x}%
        \ifhs@inline
         \hs@endInline
         \let\next=\relax
        \else
         \xdef\hs@tok{}%
         \let\next=\hs@str@state
        \fi
   \or  % NL - newline
        \hs@emitnum{0x}%
        \ifhs@inline
         \hs@space=\hswordspace
         \let\next=\hs@lex@state
        \else
         \let\next=\hs@newline@state
        \fi
   \else
        \errmessage{Illegal character in Haskell mode: #1}%
 \fi
 \next}

\def\hs@chr@state#1{%
 \ifnum`#1=`'
  \hs@emitchr
  \let\next=\hs@lex@state
 \else\ifnum`#1=92
  \xdef\hs@tok{\hs@tok#1}%
  \let\next=\hs@chresc@state
 \else
  \xdef\hs@tok{\hs@tok#1}%
  \let\next=\hs@chr@state
 \fi\fi
 \next}

\def\hs@chresc@state#1{%
 \xdef\hs@tok{\hs@tok#1}\hs@chr@state}

\def\hs@str@state{%
 \def\hs@strprefix{\hs@symface``}%
 \hs@strchr@state}

\def\hs@strchr@state#1{%
 \ifx#1"
  \setbox255=\hbox{\hs@strprefix\hs@strface\hs@tok\hs@symface''}%
  \hs@emit
  \let\next=\hs@lex@state
 \else\ifnum`#1=92
  \xdef\hs@tok{\hs@tok#1}%
  \let\next=\hs@stresc@state
 \else
  \xdef\hs@tok{\hs@tok#1}%
  \let\next=\hs@strchr@state
 \fi\fi
 \next}

\def\hs@stresc@state#1{%
 \hs@getcc#1%
 \ifnum\hs@cc=\hs@SP
  \let\next=\hs@gap@state
 \else\ifnum\hs@cc=\hs@NL
  \let\next=\hs@gapnewline@state
 \else
  \xdef\hs@tok{\hs@tok#1}%
  \let\next=\hs@strchr@state
 \fi\fi
 \next}

\def\hs@gap@state#1{%
 \hs@getcc#1%
 \ifnum\hs@cc=\hs@SP
  \let\next=\hs@gap@state
 \else\ifnum\hs@cc=\hs@NL
  \let\next=\hs@gapnewline@state
 \else
  \ifnum`#1=92
   \xdef\hs@tok{\hs@tok\hs@#1}%
   \let\next=\hs@strchr@state
  \else
   \errmessage{Unexpected character in a gap: #1}%
  \fi
 \fi\fi
 \next}

\def\hs@gapnewline@state#1{%
 \setbox255=\hbox{\hs@strprefix\hs@strface\hs@tok}%
 \hs@emit
 \hs@outputline
 \ifx#1>
  \def\hs@strprefix{}%
  \hs@space=0pt
  \let\next=\hs@gapcode@state
 \else
  \errmessage{Literate comments cannot appear in a gap}
 \fi
 \next}

\def\hs@gapcode@state#1{%
 \hs@getcc#1%
 \ifnum\hs@cc=\hs@SP
  \ifnum`#1=9\advance\hs@indent by \hstabwidth
  \else\advance\hs@indent by \hsspacewidth\fi
  \let\next=\hs@gapcode@state
 \else\ifnum\hs@cc=\hs@NL
  \def\hs@parskip{\vskip\hsparskip\def\hs@parskip{}}%
  \let\next=\hs@gapnewline@state
 \else
  \ifnum`#1=92
   \xdef\hs@tok{#1}%
   \let\next=\hs@strchr@state
  \else
   \errmessage{Unexpected character in a gap: #1}%
  \fi
 \fi\fi
 \next}

%%% The "hidden" environment %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%

\newbox\hs@junkbox
\def\beginhidden{\begingroup\setbox\hs@junkbox=\vbox\bgroup}
\def\endhidden{\egroup\endgroup}

%%% Activate active characters %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% As we've already confiscated > as an active character, let's take < too
% and use <...> to typeset ... in italic.

% To make amends for the above quirk, I define \lt and \gt math macros
% to complement the \le, \ge, etc. already in plain TeX:
\def\inch{"}
\def\lt{<}
\def\gt{>}

% Finally, we are ready to active our three active characters:
\catcode`"=\active \let"=\hs@beginInline
\catcode`>=\active \let>=\hs@beginBird
\catcode`<=\active \let<=\hs@beginitalic

% Restore the meaning of < and > in math mode.
% WARNING: this doesn't work as well as expected. When TeX sees the $
% character, it reads the following character to see if it is another $.
% If that character is active, it attempts to expand it (a bug in TeX?!
% or just a mis-feature?) So, you must write $ >$ rather than $>$. Oh well.
\everymath{\let<\lt\let>\gt\relax}
\everydisplay{\let<\lt\let>\gt\relax}


\catcode`@=12

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% THE END %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%