https://wiki.haskell.org/api.php?action=feedcontributions&user=Frerich&feedformat=atomHaskellWiki - User contributions [en]2024-03-28T16:04:38ZUser contributionsMediaWiki 1.35.5https://wiki.haskell.org/index.php?title=Quasiquotation&diff=62039Quasiquotation2017-07-31T11:31:43Z<p>Frerich: Update link to 'Why It's Nice to be Quoted' paper; old URL caused a '403 Forbidden'</p>
<hr />
<div>= Introduction =<br />
This is a tutorial for the quasiquoting facility described in<br />
[http://www.cs.tufts.edu/comp/150PLD/Papers/QuasiQuotation.pdf Why It's Nice to be Quoted: Quasiquoting for Haskell].<br />
<br />
Quasiquoting allows programmers to use custom, domain-specific syntax to construct fragments of their program. Along with Haskell's existing support for domain specific languages, you are now free to use new syntactic forms for your EDSLs.<br />
<br />
More information on GHC's support for quasiquoting may be found:<br />
<br />
* [http://downloads.haskell.org/~ghc/latest/docs/html/users_guide/glasgow_exts.html#template-haskell-quasi-quotation Using QQ with Template Haskell]<br />
* [http://www.cs.tufts.edu/comp/150PLD/Papers/QuasiQuotation.pdf Why It's Nice to be Quoted: Quasiquoting for Haskell] :: PDF<br />
<br />
A number of production examples where the result is a string:<br />
<br />
* [http://hackage.haskell.org/package/interpolatedstring-qq Quasiquoter for Ruby-style interpolated strings]<br />
* [http://hackage.haskell.org/package/interpolatedstring-perl6 interpolatedstring-perl6 library: QuasiQuoter for Perl6-style multi-line interpolated strings with "q"]<br />
* [http://hackage.haskell.org/package/here here]<br />
* [http://hackage.haskell.org/package/heredoc heredoc]<br />
* [http://hackage.haskell.org/package/raw-strings-qq raw-strings-qq]<br />
* [http://hackage.haskell.org/package/neat-interpolation neat-interpolation]<br />
* [http://hackage.haskell.org/package/Interpolation Interpolation]<br />
* [http://hackage.haskell.org/package/QuasiText A QuasiQuoter for interpolated Text literals, with support for embedding Haskell expressions]<br />
* [http://hackage.haskell.org/package/shakespeare-text shakespeare-text]<br />
* [http://hackage.haskell.org/package/dump dump]: Shows values for expressions like <hask>let a = 1 in [d| a, map (+a) [1..3] |]</hask> by turning them into <hask>"(a) = 1 (map (+a) [1..3]) = [2,3,4]"</hask> to ease debugging and development.<br />
<br />
Additional examples which producing other things:<br />
<br />
* The [[jmacro]] JavaScript generation library.<br />
* Parsing: [http://hackage.haskell.org/package/regexqq regexqq], [http://hackage.haskell.org/package/rex rex] or [http://tanakh.github.com/Peggy/ Peggy: A Quasiquoter for a packrat parser]<br />
* [http://hackage.haskell.org/package/lighttpd-conf-qq A QuasiQuoter for lighttpd configuration files]<br />
* XML: [http://hackage.haskell.org/package/text-xml-qq text-xml-qq], [http://hackage.haskell.org/package/xml-hamlet xml-hamlet]<br />
* [http://hackage.haskell.org/package/haskell-src-meta haskell-src-meta contains quite a few QuasiQuoters], though the toy examples are no longer exported and others have been moved to [http://hackage.haskell.org/package/applicative-quoters applicative-quoters]<br />
* [http://hackage.haskell.org/package/command-qq command-qq]<br />
* [http://hackage.haskell.org/package/process-qq process-qq]<br />
* [http://hackage.haskell.org/package/Rlang-QQ Rlang-QQ is a quasiquoter for inline R]<br />
* [http://hackage.haskell.org/package/language-c-quote a quasiquoter for C syntax trees]<br />
* [http://hackage.haskell.org/package/dbus-qq dbus-qq]<br />
<br />
Other QuasiQuotation/TemplateHaskell tutorials include:<br />
* [http://quasimal.com/posts/2012-05-25-quasitext-and-quasiquoting.html A look at QuasiQuotation]<br />
<br />
Note that the syntax for quasiquotation has changed since the paper was written: in GHC 7 one writes <hask>[expr|...|]</hask> instead of <hask>[:expr|...|]</hask>. GHC 6.12 uses <hask>[$expr|...|]</hask>. Quasiquotation appeared in GHC 6.9 and is enabled with the <code>QuasiQuotes</code> language option (<code>-XQuasiQuotes</code> on the command line or <hask>{-# LANGUAGE QuasiQuotes #-}</hask> in a source file).<br />
<br />
We show how to build a quasiquoter for a simple mathematical expression<br />
language. Although the example is small, it demonstrates all aspects of building<br />
a quasiquoter. We do not mean to suggest that one gains much from a quasiquoter<br />
for such a small language relative to using abstract syntax directly except from<br />
a pedagogical point of view---this is just a tutorial!<br />
<br />
The tutorial is runnable if its contents is placed in files as follows:<br />
<br />
Place the contents of the [[#Syntax]] and [[#Parsing]] sections in the file <code>Expr.hs</code><br />
with header<br />
<br />
<haskell><br />
{-# LANGUAGE DeriveDataTypeable #-}<br />
module Expr (Expr(..),<br />
BinOp(..),<br />
eval,<br />
parseExpr)<br />
where<br />
<br />
import Data.Generics<br />
import Text.ParserCombinators.Parsec<br />
</haskell><br />
<br />
Place the contents of the section [[#The Quasiquoter]] in a<br />
file <code>Expr/Quote.hs</code> with header<br />
<br />
<haskell><br />
module Expr.Quote (expr) where<br />
<br />
import Data.Generics<br />
import qualified Language.Haskell.TH as TH<br />
import Language.Haskell.TH.Quote<br />
<br />
import Expr<br />
</haskell><br />
<br />
= Syntax =<br />
<br />
Our simple expression language consists of integers, the standard operators<br />
+,x,*,/, and parenthesized expressions. We will write a single parser that takes<br />
concrete syntax for this language and transforms it to abstract syntax. Using<br />
the SYB approach to generic programming, we will then use this parser to produce<br />
expression and pattern quasiquoters. Our quasiquoter will allow us to write<br />
<hask>[expr|1 + 3|]</hask> directly in Haskell source code instead of the<br />
corresponding abstract syntax.<br />
<br />
An obvious datatype for the abstract syntax of this simple language is:<br />
<br />
<haskell><br />
data Expr = IntExpr Integer<br />
| BinopExpr (Integer -> Integer -> Integer) Expr Expr<br />
deriving(Show)<br />
</haskell><br />
<br />
Unfortunately, this won't do for our quasiquoter. First of all, the SYB<br />
technique we use cannot handle function types in a generic way, so the BinopExpr<br />
constructor must be modified. SYB also requires that we derive Typeable and<br />
Data, a trivial change. Finally, we want to support antiquoting for two<br />
syntactic categories, expressions and integers. With antiquoting support, we can<br />
write [expr|$x + $int:y|] where x and y are in-scope variables with types Expr<br />
and Integer, respectively. The final data types for our abstract syntax are:<br />
<br />
<haskell><br />
data Expr = IntExpr Integer<br />
| AntiIntExpr String<br />
| BinopExpr BinOp Expr Expr<br />
| AntiExpr String<br />
deriving(Show, Typeable, Data)<br />
<br />
data BinOp = AddOp<br />
| SubOp<br />
| MulOp<br />
| DivOp<br />
deriving(Show, Typeable, Data)<br />
</haskell><br />
<br />
An evaluator for our abstract syntax can be written as follows:<br />
<br />
<haskell><br />
eval :: Expr -> Integer<br />
eval (IntExpr n) = n<br />
eval (BinopExpr op x y) = (opToFun op) (eval x) (eval y)<br />
where<br />
opToFun AddOp = (+)<br />
opToFun SubOp = (-)<br />
opToFun MulOp = (*)<br />
opToFun DivOp = div<br />
</haskell><br />
<br />
= Parsing =<br />
<br />
We use Parsec to write a parser for our expression language. Note that we have<br />
(somewhat arbitrarily) chosen the syntax for antiquotaton to be as in the above<br />
example; a quasiquoter may choose whatever syntax she wishes.<br />
<br />
<haskell><br />
small = lower <|> char '_'<br />
large = upper<br />
idchar = small <|> large <|> digit <|> char '\''<br />
<br />
lexeme p = do{ x <- p; spaces; return x }<br />
symbol name = lexeme (string name)<br />
parens p = between (symbol "(") (symbol ")") p<br />
<br />
expr :: CharParser st Expr<br />
expr = term `chainl1` addop<br />
<br />
term :: CharParser st Expr<br />
term = factor `chainl1` mulop<br />
<br />
factor :: CharParser st Expr<br />
factor = parens expr <|> integer <|> try antiIntExpr <|> antiExpr<br />
<br />
mulop = do{ symbol "*"; return $ BinopExpr MulOp }<br />
<|> do{ symbol "/"; return $ BinopExpr DivOp }<br />
<br />
addop = do{ symbol "+"; return $ BinopExpr AddOp }<br />
<|> do{ symbol "-"; return $ BinopExpr SubOp }<br />
<br />
integer :: CharParser st Expr<br />
integer = lexeme $ do{ ds <- many1 digit ; return $ IntExpr (read ds) }<br />
<br />
ident :: CharParser s String<br />
ident = do{ c <- small; cs <- many idchar; return (c:cs) }<br />
<br />
antiIntExpr = lexeme $ do{ symbol "$int:"; id <- ident; return $ AntiIntExpr id }<br />
antiExpr = lexeme $ do{ symbol "$"; id <- ident; return $ AntiExpr id }<br />
</haskell><br />
<br />
The helper function parseExpr takes a source code position (consisting of a file<br />
name, line and column) and a string and returns a value of type Expr. This<br />
helper function also ensures that we can parse the whole string rather than just<br />
a prefix.<br />
<br />
<haskell><br />
parseExpr :: Monad m => (String, Int, Int) -> String -> m Expr<br />
parseExpr (file, line, col) s =<br />
case runParser p () "" s of<br />
Left err -> fail $ show err<br />
Right e -> return e<br />
where<br />
p = do pos <- getPosition<br />
setPosition $<br />
(flip setSourceName) file $<br />
(flip setSourceLine) line $<br />
(flip setSourceColumn) col $<br />
pos<br />
spaces<br />
e <- expr<br />
eof<br />
return e<br />
</haskell><br />
<br />
= The Quasiquoter =<br />
<br />
Remember, our quasiquoter allows us to write expression in our simple language,<br />
such as [expr|2 * 3|], directly in Haskell source code. This requires that the<br />
variable expr be in-scope when the quasiquote is encountered, and that it is<br />
bound to a value of type Language.Haskell.TH.Quote.QuasiQuoter, which contains<br />
an expression quoter and a pattern quoter. Note that expr must obey the same<br />
stage restrictions as Template Haskell; in particular, it may not be defined in<br />
the same module where it is used as a quasiquoter, but must be imported.<br />
<br />
Our expression and pattern quoters are quoteExprExp and quoteExprPat,<br />
respectively, so our quasiquoter expr is written as follows:<br />
<br />
<haskell><br />
quoteExprExp :: String -> TH.ExpQ<br />
quoteExprPat :: String -> TH.PatQ<br />
<br />
expr :: QuasiQuoter<br />
expr = QuasiQuoter { quoteExp = quoteExprExp,<br />
quotePat = quoteExprPat<br />
-- with ghc >= 7.4, you could also<br />
-- define quoteType and quoteDec for<br />
-- quasiquotes in those places too<br />
}<br />
</haskell><br />
<br />
Our quasiquoters re-use the parser we wrote in the previous section, parseExpr,<br />
and make use of the generic functions dataToExpQ and dataToPatQ (described in<br />
the Haskell Workshop paper). These functions, from the Language.Haskell.TH.Quote<br />
package, take a Haskell value and reflect it back into the language as Template<br />
Haskell abstract syntax. The catch is that we don't want to handle all values<br />
generically: antiquoted values must be handled specially. Consider the AntiExpr<br />
constructor; we don't want this constructor to be mapped to Template Haskell<br />
abstract syntax for the AntiExpr constructor, but to abstract syntax for the<br />
Haskell variable named by the constructor's argument. The extQ combinator allows<br />
us to do this nicely by defining a function antiExprExp that handles<br />
antiquotations.<br />
<br />
<haskell><br />
quoteExprExp s = do loc <- TH.location<br />
let pos = (TH.loc_filename loc,<br />
fst (TH.loc_start loc),<br />
snd (TH.loc_start loc))<br />
expr <- parseExpr pos s<br />
dataToExpQ (const Nothing `extQ` antiExprExp) expr<br />
<br />
antiExprExp :: Expr -> Maybe (TH.Q TH.Exp)<br />
antiExprExp (AntiIntExpr v) = Just $ TH.appE (TH.conE (TH.mkName "IntExpr"))<br />
(TH.varE (TH.mkName v))<br />
antiExprExp (AntiExpr v) = Just $ TH.varE (TH.mkName v)<br />
antiExprExp _ = Nothing<br />
</haskell><br />
<br />
The corresponding code for patterns is:<br />
<br />
<haskell><br />
quoteExprPat s = do loc <- TH.location<br />
let pos = (TH.loc_filename loc,<br />
fst (TH.loc_start loc),<br />
snd (TH.loc_start loc))<br />
expr <- parseExpr pos s<br />
dataToPatQ (const Nothing `extQ` antiExprPat) expr<br />
<br />
antiExprPat :: Expr -> Maybe (TH.Q TH.Pat)<br />
antiExprPat (AntiIntExpr v) = Just $ TH.conP (TH.mkName "IntExpr")<br />
[TH.varP (TH.mkName v)]<br />
antiExprPat (AntiExpr v) = Just $ TH.varP (TH.mkName v)<br />
antiExprPat _ = Nothing<br />
</haskell><br />
<br />
= Examples =<br />
<br />
We can now try out a few examples by invoking ghci as follows: <code>ghci -XQuasiQuotes Expr/Quote</code><br />
<br />
<pre><br />
> [expr|1 + 3 + 5|]<br />
BinopExpr AddOp (BinopExpr AddOp (IntExpr 1) (IntExpr 3)) (IntExpr 5) <br />
> eval [expr|1 + 3 + 5|]<br />
9 <br />
</pre><br />
<br />
Taking advantage of our quasiquoter, we can re-write our evaluator so it uses<br />
concrete syntax:<br />
<br />
<haskell><br />
eval' :: Expr -> Integer<br />
eval' [expr|$int:x|] = x<br />
eval' [expr|$x + $y|] = eval' x + eval' y<br />
eval' [expr|$x - $y|] = eval' x - eval' y<br />
eval' [expr|$x * $y|] = eval' x * eval' y<br />
eval' [expr|$x / $y|] = eval' x `div` eval' y<br />
</haskell><br />
<br />
Let's make sure it works as advertised:<br />
<br />
<pre><br />
> eval [expr|1 + 2 + 3|] == eval' [expr|1 + 2 + 3|]<br />
True <br />
> eval [expr|1 + 3 * 5|] == eval' [expr|1 + 3 * 5|]<br />
True <br />
</pre></div>Frerichhttps://wiki.haskell.org/index.php?title=Unicode-symbols&diff=58262Unicode-symbols2014-06-02T20:38:38Z<p>Frerich: Don't mention unicode-haskell vim plugin anymore, it's dead.</p>
<hr />
<div>[[Category:Packages]]<br />
<br />
== Overview ==<br />
<br />
An overview of the packages that provide Unicode symbols. <br />
<br />
Naming: A package '''<tt>X-unicode-symbols</tt>''' defines new symbols for functions and operators from the package '''<tt>X</tt>'''.<br />
<br />
All symbols are documented with their actual definition and information regarding their Unicode code point. They should be completely interchangeable with their definitions.<br />
<br />
Alternatives for existing operators have the same fixity. New operators will have a suitable fixity defined.<br />
<br />
==== UnicodeSyntax ====<br />
<br />
GHC offers the [http://www.haskell.org/ghc/docs/latest/html/users_guide/syntax-extns.html#unicode-syntax UnicodeSyntax] language extension. If you decide to use Unicode in your Haskell source then this extension can greatly improve how it looks.<br />
<br />
Simply put the following above a module to enable unicode syntax:<br />
{-# LANGUAGE UnicodeSyntax #-}<br />
<br />
== base-unicode-symbols ==<br />
<br />
Extra symbols for the [http://hackage.haskell.org/package/base base] package.<br />
<br />
API docs: http://hackage.haskell.org/package/base-unicode-symbols<br />
github: https://github.com/roelvandijk/base-unicode-symbols<br />
checkout: git clone git://github.com/roelvandijk/base-unicode-symbols.git<br />
<br />
==== Problematic symbols ====<br />
{| class="wikitable" border="1"<br />
|-<br />
! Original<br />
! Symbol<br />
! Code point<br />
! Name<br />
|-<br />
| not<br />
| &#xAC;<br />
| U+AC<br />
| NOT SIGN<br />
|-<br />
| lambda<br />
| &#x3BB;<br />
| U+03BB<br />
| GREEK SMALL LETTER LAMDA<br />
|}<br />
The problem with the NOT symbol is that you would like to use it as an unary prefix operator:<br />
&not;(&not;x) &equiv; x<br />
Unfortunately this is not valid Haskell. The following is:<br />
(&not;)((&not;)x) &equiv; x<br />
But you can hardly call that an improvement over the simple:<br />
not (not x) &equiv; x<br />
<br />
The problem with the LAMBDA symbol is that it is classified as an alphabetic character, so it can be used as part of a name. See the [http://hackage.haskell.org/trac/ghc/ticket/1102 discussion for GHC].<br />
<br />
==== New symbol ideas ====<br />
(''please add your own'')<br />
<br />
I'm thinking of adding the following symbol as another alternative for (*).<br />
<br />
{| class="wikitable" border="1"<br />
|-<br />
! Original<br />
! Symbol<br />
! Code point<br />
! Name<br />
|-<br />
| (*)<br />
| &#xD7;<br />
| U+D7<br />
| MULTIPLICATION SIGN<br />
|}<br />
<br />
2 * 3 &equiv; 6<br />
2 &#x22C5; 3 &equiv; 6<br />
2 &#xD7; 3 &equiv; 6<br />
<br />
A disadvantage of this symbol is its similarity to the letter x:<br />
sqr x = x &#xD7; x<br />
<br />
{| class="wikitable" border="1"<br />
|-<br />
! Original<br />
! Symbol<br />
! Code point<br />
! Name<br />
|-<br />
| Bool<br />
| &#x1D539;<br />
| U+1D539<br />
| MATHEMATICAL DOUBLE-STRUCK CAPITAL B<br />
|}<br />
<br />
This idea is an extension of<br />
<br />
type &#x2124; = Integer<br />
<br />
and<br />
<br />
type &#x211A; = Ratio &#x2124;<br />
<br />
The advantage is that it looks nice and that it is a logical extension of &#x2124;, &#x211A; and &#x211D;. The disadvantage is that there is no documented prior use of this character to denote boolean values. This could be detrimental to the readability of code.<br />
<br />
Example:<br />
<br />
(&#x2227;) &#x2237; &#x1D539; &#x2192; &#x1D539; &#x2192; &#x1D539;<br />
<br />
== containers-unicode-symbols ==<br />
<br />
Extra symbols for the [http://hackage.haskell.org/package/containers containers] package.<br />
<br />
API docs: http://hackage.haskell.org/package/containers-unicode-symbols<br />
github: https://github.com/roelvandijk/containers-unicode-symbols<br />
checkout: git clone git://github.com/roelvandijk/containers-unicode-symbols.git <br />
<br />
==== New symbol ideas ==== <br />
(''please add your own'')<br />
<br />
== Input methods ==<br />
<br />
These symbols are all very nice but how do you type them?<br />
<br />
Wikipedia has a helpful article: http://en.wikipedia.org/wiki/Unicode_input<br />
<br />
(''please add info for other editors'')<br />
<br />
=== Emacs ===<br />
<br />
'''Direct'''<br />
<br />
Enter symbols directly: <tt>[http://www.gnu.org/software/emacs/manual/html_node/emacs/International-Chars.html C-x 8 RET]</tt> (<tt>ucs-insert</tt>), then type either the character's name or its hexadecimal code point.<br />
<br />
'''TeX input method'''<br />
<br />
The TeX input method, invoked with <tt>M-x set-input-method</tt> and entering <tt>TeX</tt> allows you to enter Unicode characters by typing in TeX-like sequences. For example, typing <tt>\lambda</tt> inserts a λ.<br />
<br />
This is probably the most convenient input method for casual use.<br />
<br />
A list of available sequences may be viewed with <tt>M-x describe-input-method</tt><br />
<br />
'''Custom input method'''<br />
<br />
I wrote my own input method:<br />
<br />
github: https://github.com/roelvandijk/emacs-haskell-unicode-input-method<br />
checkout: git clone git://github.com/roelvandijk/emacs-haskell-unicode-input-method.git<br />
<br />
To automically load in haskell-mode put the following code in your .emacs file:<br />
(require 'haskell-unicode-input-method)<br />
(add-hook 'haskell-mode-hook <br />
(lambda () (set-input-method "haskell-unicode")))<br />
<br />
Make sure the directory containing the .elisp file is in your load-path, for example:<br />
(add-to-list 'load-path "~/.elisp/emacs-haskell-unicode-input-method")<br />
<br />
To manually enable use <tt>M-x set-input-method</tt> or <tt>C-x RET C-\</tt> with <tt>haskell-unicode</tt>. Note that the elisp file must be evaluated for this to work.<br />
<br />
Now you can simply type <tt>-></tt> and it is immediately replaced with &rarr;. Use <tt>C-\</tt> to toggle the input method. To see a table of all key sequences use <tt>M-x describe-input-method haskell-unicode</tt>. A sequence like <= is ambiguous and can mean either <tt>&lArr;</tt> or <tt>&le;</tt>. Typing it presents you with a choice. Type 1 or 2 to select an option or keep typing to use the default option.<br />
<br />
If you don't like the highlighting of partially matching tokens you can turn it off:<br />
<br />
(setq input-method-highlight-flag nil)<br />
<br />
'''Abbrev mode'''<br />
<br />
The [http://www.gnu.org/software/emacs/manual/html_node/emacs/Abbrevs.html Abbrev mode] is not suitable since it only deals with ''words'', not ''operators''.<br />
<br />
'''Agda'''<br />
<br />
Use Agda's [http://wiki.portal.chalmers.se/agda/pmwiki.php?n=Docs.UnicodeInput input method].<br />
<br />
=== Vim ===<br />
<br />
(''real Vim users might want to expand this section'')<br />
<br />
'''Direct'''<br />
<br />
* Decimal value: type '''C-Vnnn''' where 0 &le; nnn &le; 255.<br />
* Octal value: type '''C-VOnnn''' or '''C-Vonnn''' where 0 &le; nnn &le; 377.<br />
* Hex value: type '''C-VXnn''' or '''C-Vxnn''' where 0 &le; nn &le; FF.<br />
* Hex value for BMP codepoints: type '''C-Vunnnn''' where 0 &le; nnnn &le; FFFF.<br />
* Hex value for any codepoint: type '''C-VUnnnnnnnn''' where 0 &le; nnnnnnnn &le; FFFFFFFF.<br />
<br />
'''Digraphs'''<br />
<br />
Vim's digraphs can be used to type many Unicode symbols with somewhat memorable key combinations.<br />
<br />
Digraphs are entered with <tt>C-K</tt> plus two keystrokes in insert mode. Many of the simplest symbols are entered with the same two characters they'd substitute for:<br />
<br />
* <tt>C-K ::</tt> inserts ∷<br />
* <tt>C-K =></tt> inserts ⇒<br />
* <tt>C-K -></tt> inserts →<br />
* <tt>C-K <-</tt> inserts ←<br />
<br />
Other typeable symbols include:<br />
<br />
* <tt>C-K FA</tt> inserts ∀<br />
* <tt>C-K AN</tt> inserts ∧<br />
* <tt>C-K OR</tt> inserts ∨<br />
* <tt>C-K NO</tt> inserts ¬<br />
* <tt>C-K (-</tt> inserts ∈<br />
* <tt>C-K !=</tt> inserts ≠<br />
* <tt>C-K =<</tt> inserts ≤<br />
* <tt>C-K >=</tt> inserts ≥<br />
<br />
A complete list of default digraphs is available in the documentation under <tt>:help digraphs-default</tt>.<br />
<br />
Custom digraphs can be defined in one's <tt>.vimrc</tt>. For example, if one wants to type <tt>C-K ZZ</tt> to insert ℤ:<br />
<br />
digraph ZZ 8484<br />
<br />
Here, 8484 is the decimal value of the character ℤ.<br />
<br />
'''Automatic Unicode Transformation'''<br />
<br />
The Vim conceal definitions in haskellmode-vim pleasantly mask most of usual symbols with the unicode equivalent but have no effect on the actual source code. While in normal mode, the concealed characters on the current line will be displayed as ASCII. In insert mode and on lines other than the current one in normal mode, Unicode characters will be displayed.<br />
<br />
=== SciTE ===<br />
<br />
See [[Tips_for_using_SciTE_with_Haskell]]<br />
<br />
=== Sublime Text 2 ===<br />
<br />
Syntax highlighting for the GHC unicode syntax is not supported in the default configuration as of version 2.0.1. However the following patch, when applied to <code>Packages/Haskell/Haskell.tmLanguage</code>, does enable this: https://gist.github.com/3744568<br />
<br />
Insert the following snippet into user key bindings to conveniently type unicode operators in Haskell code: https://gist.github.com/3766192 . For example, typing "->" will automatically insert "→".<br />
<br />
=== System wide ===<br />
<br />
'''m17n input methods'''<br />
<br />
A set of input methods has been written by Urs Holzer for the [http://www.m17n.org m17n] library. The main goal of Urs is to build input methods for mathematical characters. However, most of the symbols used in the *-unicode-symbols packages can be written using Urs's methods. More information is available at [http://www.andonyar.com/rec/2008-03/mathinput/ Input Methods for Mathematics] page. For most Linux distributions, just download a [http://www.andonyar.com/rec/2008-03/mathinput/methods.tar.gz tarball], extract *.mim files to /usr/share/m17n and enable iBus for input methods.<br />
<br />
== Fonts ==<br />
<br />
The following free fonts have good Unicode coverage:<br />
<br />
* [http://www.gnome.org/fonts/ Bitstream Vera Font Family]<br />
* [http://dejavu-fonts.org/wiki/Main_Page DejaVu Font Family]<br />
* [http://linuxlibertine.sourceforge.net/ Linux Libertine Font]<br />
* [https://www.redhat.com/promo/fonts/ RedHat Liberation Fonts]</div>Frerichhttps://wiki.haskell.org/index.php?title=Unicode-symbols&diff=41671Unicode-symbols2011-08-18T06:07:09Z<p>Frerich: Mention unicode-haskell.vim script for vim users.</p>
<hr />
<div>[[Category:Packages]]<br />
<br />
== Overview ==<br />
<br />
An overview of the packages that provide Unicode symbols. <br />
<br />
Naming: A package '''<tt>X-unicode-symbols</tt>''' defines new symbols for functions and operators from the package '''<tt>X</tt>'''.<br />
<br />
All symbols are documented with their actual definition and information regarding their Unicode code point. They should be completely interchangeable with their definitions.<br />
<br />
Alternatives for existing operators have the same fixity. New operators will have a suitable fixity defined.<br />
<br />
==== UnicodeSyntax ====<br />
<br />
GHC offers the [http://www.haskell.org/ghc/docs/latest/html/users_guide/syntax-extns.html#unicode-syntax UnicodeSyntax] language extension. If you decide to use Unicode in your Haskell source then this extension can greatly improve how it looks.<br />
<br />
Simply put the following above a module to enable unicode syntax:<br />
{-# LANGUAGE UnicodeSyntax #-}<br />
<br />
== base-unicode-symbols ==<br />
<br />
Extra symbols for the [http://hackage.haskell.org/package/base base] package.<br />
<br />
API docs: http://hackage.haskell.org/package/base-unicode-symbols<br />
github: https://github.com/roelvandijk/base-unicode-symbols<br />
checkout: git clone git://github.com/roelvandijk/base-unicode-symbols.git<br />
<br />
==== Problematic symbols ====<br />
{| class="wikitable" border="1"<br />
|-<br />
! Original<br />
! Symbol<br />
! Code point<br />
! Name<br />
|-<br />
| not<br />
| &#xAC;<br />
| U+AC<br />
| NOT SIGN<br />
|}<br />
The problem with this symbol is that you would like to use it as an unary prefix operator:<br />
&not;(&not;x) &equiv; x<br />
Unfortunately this is not valid Haskell. The following is:<br />
(&not;)((&not;)x) &equiv; x<br />
But you can hardly call that an improvement over the simple:<br />
not (not x) &equiv; x<br />
<br />
==== New symbol ideas ====<br />
(''please add your own'')<br />
<br />
I'm thinking of adding the following symbol as another alternative for (*).<br />
<br />
{| class="wikitable" border="1"<br />
|-<br />
! Original<br />
! Symbol<br />
! Code point<br />
! Name<br />
|-<br />
| (*)<br />
| &#xD7;<br />
| U+D7<br />
| MULTIPLICATION SIGN<br />
|}<br />
<br />
2 * 3 &equiv; 6<br />
2 &#x22C5; 3 &equiv; 6<br />
2 &#xD7; 3 &equiv; 6<br />
<br />
A disadvantage of this symbol is its similarity to the letter x:<br />
sqr x = x &#xD7; x<br />
<br />
{| class="wikitable" border="1"<br />
|-<br />
! Original<br />
! Symbol<br />
! Code point<br />
! Name<br />
|-<br />
| Bool<br />
| &#x1D539;<br />
| U+1D539<br />
| MATHEMATICAL DOUBLE-STRUCK CAPITAL B<br />
|}<br />
<br />
This idea is an extension of<br />
<br />
type &#x2115; = Integer<br />
<br />
and<br />
<br />
type &#x211A; = Ratio &#x2115;<br />
<br />
The advantage is that it looks nice and that it is a logical extension of &#x2115;, &#x211A; and &#x211D;. The disadvantage is that their is no documented prior use of this character to denote boolean values. This could be detrimental to the readability of code.<br />
<br />
Example:<br />
<br />
(&#x2227;) &#x2237; &#x1D539; &#x2192; &#x1D539; &#x2192; &#x1D539;<br />
<br />
== containers-unicode-symbols ==<br />
<br />
Extra symbols for the [http://hackage.haskell.org/package/containers containers] package.<br />
<br />
API docs: http://hackage.haskell.org/package/containers-unicode-symbols<br />
github: https://github.com/roelvandijk/containers-unicode-symbols<br />
checkout: git clone git://github.com/roelvandijk/containers-unicode-symbols.git <br />
<br />
==== New symbol ideas ==== <br />
(''please add your own'')<br />
<br />
== Input methods ==<br />
<br />
These symbols are all very nice but how do you type them?<br />
<br />
Wikipedia has a helpful article: http://en.wikipedia.org/wiki/Unicode_input<br />
<br />
(''please add info for other editors'')<br />
<br />
=== Emacs ===<br />
<br />
'''Direct'''<br />
<br />
Enter symbols directly: <tt>[http://www.gnu.org/software/emacs/manual/html_node/emacs/International-Chars.html C-x 8 RET]</tt> (<tt>ucs-insert</tt>), then type either the character's name or its hexadecimal code point.<br />
<br />
'''TeX input method'''<br />
<br />
The TeX input method, invoked with <tt>M-x set-input-method</tt> and entering <tt>TeX</tt> allows you to enter Unicode characters by typing in TeX-like sequences. For example, typing <tt>\lambda</tt> inserts a λ.<br />
<br />
This is probably the most convenient input method for casual use.<br />
<br />
A list of available sequences may be viewed with <tt>M-x describe-input-method</tt><br />
<br />
'''Custom input method'''<br />
<br />
I wrote my own input method:<br />
<br />
github: https://github.com/roelvandijk/emacs-haskell-unicode-input-method<br />
checkout: git clone git://github.com/roelvandijk/emacs-haskell-unicode-input-method.git<br />
<br />
To automically load in haskell-mode put the following code in your .emacs file:<br />
(require 'haskell-unicode-input-method)<br />
(add-hook 'haskell-mode-hook <br />
(lambda () (set-input-method "haskell-unicode")))<br />
<br />
Make sure the directory containing the .elisp file is in your load-path, for example:<br />
(add-to-list 'load-path "~/.elisp/emacs-haskell-unicode-input-method")<br />
<br />
To manually enable use '''<tt>M-x set-input-method</tt>''' or '''<tt>C-x RET C-\</tt>''' with '''<tt>haskell-unicode</tt>'''. Note that the elisp file must be evaluated for this to work.<br />
<br />
Now you can simply type '''->''' and it is immediately replaced with '''&rarr;'''. Use '''<tt>C-\</tt>''' to toggle the input method. To see a table of all key sequences use '''<tt>M-x describe-input-method haskell-unicode</tt>'''. A sequence like <= is ambiguous and can mean either '''&lArr;''' or '''&le;'''. Typing it presents you with a choice. Type 1 or 2 to select an option or keep typing to use the default option.<br />
<br />
If you don't like the highlighting of partially matching tokens you can turn it off:<br />
<br />
(setq input-method-highlight-flag nil)<br />
<br />
'''Abbrev mode'''<br />
<br />
The [http://www.gnu.org/software/emacs/manual/html_node/emacs/Abbrevs.html Abbrev mode] is not suitable since it only deals with ''words'', not ''operators''.<br />
<br />
'''Agda'''<br />
<br />
Use Agda's [http://wiki.portal.chalmers.se/agda/pmwiki.php?n=Docs.UnicodeInput input method].<br />
<br />
=== Vim ===<br />
<br />
(''real Vim users might want to expand this section'')<br />
<br />
'''Direct'''<br />
<br />
* Decimal value: type '''C-Vnnn''' where 0 &le; nnn &le; 255.<br />
* Octal value: type '''C-VOnnn''' or '''C-Vonnn''' where 0 &le; nnn &le; 377.<br />
* Hex value: type '''C-VXnn''' or '''C-Vxnn''' where 0 &le; nn &le; FF.<br />
* Hex value for BMP codepoints: type '''C-Vunnnn''' where 0 &le; nnnn &le; FFFF.<br />
* Hex value for any codepoint: type '''C-VUnnnnnnnn''' where 0 &le; nnnnnnnn &le; FFFFFFFF.<br />
<br />
'''Automatic Unicode Transformation'''<br />
<br />
Furthermore, there is a Haskell file type plugin called [https://github.com/frerich/unicode-haskell unicode-haskell] which automatically transforms ASCII character sequences (e.g. -> and many others) to Unicode when loading Haskell source code - and the data is converted back when saving. That way, the source code remains plain ASCII on disk but uses nice Unicode characters in vim/gvim. Furthermore, the plugin will automatically replace ASCII sequences with their Unicode equivalents as you type.<br />
<br />
=== System wide ===<br />
<br />
'''m17n input methods'''<br />
<br />
A set of input methods has been written by Urs Holzer for the [http://www.m17n.org m17n] library. The main goal of Urs is to build input methods for mathematical characters. However, most of the symbols used in the *-unicode-symbols packages can be written using Urs's methods. More information is available at [http://www.andonyar.com/rec/2008-03/mathinput/ Input Methods for Mathematics] page. For most Linux distributions, just download a [http://www.andonyar.com/rec/2008-03/mathinput/methods.tar.gz tarball], extract *.mim files to /usr/share/m17n and enable iBus for input methods.<br />
<br />
== Fonts ==<br />
<br />
The following free fonts have good Unicode coverage:<br />
<br />
* [http://www.gnome.org/fonts/ Bitstream Vera Font Family]<br />
* [http://dejavu-fonts.org/wiki/Main_Page DejaVu Font Family]<br />
* [http://linuxlibertine.sourceforge.net/ Linux Libertine Font]<br />
* [https://www.redhat.com/promo/fonts/ RedHat Liberation Fonts]</div>Frerich