How could I remove the "if ... then ... else ..." keywords in Haskell (GHC)? - haskell

I would like to remove the if ... then ... else ... keywords, because I am embedding a language/DSL in Haskell. if, then and else convey a lot of meaning in many domains, and it would be great if I could redefine (or leave them undefined) them to reflect the nature of the language/domain.
I've searched on Google and stackoverflow, but found nothing. (I did find an old thread on why if ... then ... else ... was included as keywords in Haskell.)
My IDE is in Leksah, and, if the keywords can be removed, it would also be nice to have a setting to change the if ... then ... else ... keywords back to their normal font/color/unbold.
I've already tried a naming convention of if' for if and so on. It doesn't feel as good, especially when I want to define if and if', and have to define if' and if'' instead, or if1 and if2. The presence of both if' and if might also be confusing. (The confusion is not that serious an issue in my situation as the users of the DSL are Haskell programmers, but I suppose it can help in other situations).
Summarizing the responses to date:
Use the RebindableSyntax extension to GHC. Not as general as removing the keywords: the syntax of Haskell's if-then-else is retained. (Frerich Raabe)
Workaround: Use very similar words/names, by using data Conditional b a = If b (Then a) (Else a) (only applicable in some contexts). (C. A. McCann)
If RebindableSyntax is a relatively new feature, then it's unlikely to find a more general way, at least not till the next version of GHC.

The RebindableSyntax extension to GHC lets you overload if ... then ... else expressions with your own version. In particular, the ifThenElse function is used to define alternative meanings. if e1 then e2 else e3" means ifThenElse e1 e2 e3.
See the blog article Rebindable if..then..else expressions for a nice discussion of this feature, including some examples.

You can't remove existing keywords. As was pointed out you can use RebindableSyntax, but that might not do what you want.
The only thing getting close to removing keywords is to turn on the CPP option and doing something like
#define if if_
#define then then_
#define else else_
The preprocessor will then expand if/then/else to if_/then_/else_.

How about:
cond True t _ = t
cond False _ f = f

Related

Link two functions without a space between them

I am writing documentation for a library using haddock, and, for reasons that are not really necessary to explain, I need to include a little code block in my documentation that looks like:
z(<>)
Importantly there can be no space between z and (<>). It may be a bit esoteric but
z (<>)
would make my documentation incorrect, even if it is more stylistically correct.
Now I believe that hyperlinks to both z and (<>) would be helpful. Neither has a very informative name, so a link that helps people remember their definitions and purpose is nice.
So my code without the hyperlinks looks like:
#z(<>)#
And to add hyperlinks I just use single quotes:
#'z''(<>)'#
Except that doesn't work, haddock sees 'z'' and thinks that I mean to link z' (a function that does exist in my module), and then just leaves the rest alone. The rendered output looks like
z'(<>)'
Now as an experiment I deleted the definition of z', however the only difference this makes is that the link to z' goes away. The raw text remains the same. The next thing I tried was ditching #s altogether and did
'z''(<>)'
Which also created a hyperlink to z' and left the rest untouched, the same problem as earlier except now nothing is in a code block.
How can I make a code block that links two functions without a space between?
You can separate the two functions into different code blocks. If there is no space between the code blocks, it will appear no different than a single code block. So
#'z'##'(<>)'#
will render as desired.
You can also do it in one code block by moving the 's inside of the parentheses to only surround <>.
#'z'('<>')#
This will render slightly differently with the parentheses not being part of any hyperlink, however this may be desired.
Here is an alternative solution to add to the answer you already provided:
You can mix and match ' and `. These two will also be rendered correctly by haddock:
-- | #`z`'(<>)'#
-- | #'z'`(<>)`#
At the same time I've tried your solution #'z'##'(<>)'# and for some reason it did not render for me properly, but with haddock you never know.
Here are all of the ones that I've tried:
-- * #'z'##'(<>)'#
-- * #'z'('<>')#
-- * #'z'`(<>)`#
-- * #`z`'(<>)'#
With corresponding result:

violation of Haskell indentation rules for if-then-else

According to the Haskell indentation rules, "Code which is part of some expression should be indented further in than the beginning of that expression". However, I found the following example, which seems to violate the rule above, compiles without any error or warning:
someFunction :: Bool -> Int -> Int -> Int
someFunction condition a b = if condition
then a - b
else a + b
Here I am defining a function someFunction, its body is an if-then-else block. According to the indentation rule, the then block is a part of the same expression in the first line, so it should be indented further than its previous line. Yet in my example, the second line then starts at the same column as the first line, and this example compiles.
I am not sure what is going on here. I am working with GHC version 8.0.1.
I'm reasonably sure this is an artifact of a deliberate GHC variation on the indentation rule. Nice catch!
GHC reads this
foo = do
item
if a
then b
else c
item
as
foo = do {
item ;
if a ;
then b ;
else c ;
item }
which should trigger a parse error.
However, this was so common that at a certain point the GHC devs decided to allow for an optional ; before then and else. This change to the if grammar makes the code compile.
This means that if became "special", in that it does not have to indented more, but only as much as the previous item. In the code posted in the question, then is indented as much as the previous item, so there's an implicit ; before it, and that makes the code compile.
I would still try to avoid this "style", though, since it's quirky.
(Personally, I wouldn't have added this special case to GHC. But it's not a big deal, anyway.)
I now noticed that the Wikibook mentions this variant as a "proposal" for a future version of Haskell. This is a bit outdated now, and has been implemented in GHC since then.

Haskell Haddock latex equation in comments

I'd like to use latex notation for equations in my source code.
For example, I would write the following comment in some haskell source file Equations.hs:
-- | $v = \frac{dx}{dt}$
In the doc directory, this gets rendered by haddock in Equations.tex as:
{\char '44}v = frac{\char '173}dx{\char '175}{\char '173}dt{\char '175}{\char '44}
I found this function in the source for Haddock's latex backend that replaces many characters that are used in latex formatting:
latexMunge :: Char -> String -> String
...
latexMunge '$' s = "{\\char '44}" ++ s
Is there any existing functionality that allows me to bypass this and insert latex equations in comments?
No. The main reason why this (and similar features) don't exist is that it's unclear what to do with the markup in the other backends, be it HTML one, Hoogle one or whatever else someone might be using. This is fairly commonly requested but there is no common agreement and more importantly, no patches.
Technically we don't support the LaTeX backend, it's kept around compiling so that the Haskell Report can be produced. If you or someone else wants to give it some new life (and features) then we'll happily accept patches.
tl;dr: no can do. I know people simply pre-render LaTeX and insert the resulting images in with the image syntax.

Embedding a domain specific language in an OCaml toplevel -- to Camlp4 or not?

I have some code that includes a menhir-based parser for a domain specific language (a logic). For the sake of my sanity while debugging, it would be great to be able to type instances of this language (formulas) directly in the toplevel like so:
# f = << P(x,y) & x!=y >>
Is campl4/5 my only option? If yes, I find the documentation rather intimidating. Is there an example/tutorial that is close-enough to my use case and that I could conceivably adapt? (For instance, syntax extensions that introduce new keywords do not seem relevant). Thanks!
If you're willing to call a function to do the parsing, you can use ocamlmktop to include your parser into the top level. Then you can install printers for your types using #install_printer. The sessions might look like this then:
# let x = parse ()
<< type your expression here >>
# x : type = <<formatted version>>
I have used specialed printers, and they definitely help a lot with complicated types. I've never gotten around to using ocamlmktop. I always just load in my code with #load and #use.
This is a lot easier than mastering camlp4/5 (IMHO). But maybe it's a bit too crude.
Yes, you can use camlp4 and it will work reasonably well (including in the toplevel), but no, it's not well-documented, and you will have to cope with that.
For an example that is close to your use-case, see the Lambda calculus quotation example of the Camlp4 wiki.
For the toplevel, it will work easily. You can dynamically load "camlp4o.cmo" then your syntactic extension in the toplevel, or use findlib which handles that: from the toplevel, #use "topfind";;, then #camlp4o;;, then #require "myfoo.syntax";; where myfoo.syntax is the name of the findlib package you've created to deploy your extension.

What languages have a while-else type control structure, and how does it work?

A long time ago, I thought I saw a proposal to add an else clause to for or while loops in C or C++... or something like that. I don't remember how it was supposed to work -- did the else clause run if the loop exited normally but not via a break statement?
Anyway, this is tough to search for, so I thought maybe I could get some CW answers here for various languages.
What languages support adding an else clause to something other than an if statement? What is the meaning of that clause? One language per answer please.
Python.
Example use:
for element in container:
if element == target:
break
else:
# this will not be executed if the loop is quit with break.
raise ElementNotFoundError()
From the Python docs:
it is executed when the loop
terminates through exhaustion of the
list (with for) or when the condition
becomes false (with while), but not
when the loop is terminated by a break
statement.
There is so-called "Dijkstra's Loop" (also called "Dijkstra's Guarded Loop"). It was defined in The Guarded Command Language (GCL). You can find some information about it syntax and semantic in the above Wikipedia article at the section 6 Repetition: do.
Nowadays I actually know one programming language which supports this control struture directly. It is Oberon-07 (PDF, 70 KB). And it supports "Dijkstra's Loop" in thัƒ form of while statement. Take a look at section 9.6. While statements in the above PDF.
WHILE m > n DO m := m โ€“ n
ELSIF n > m DO n := n โ€“ m
END
Interestingly, neither the Python or the Oberon construct are the one I've been searching for. In C, I frequently find myself often wanting an 'otherwise' or 'elsewhile' construct that is executed only if the loop was never taken. Perhaps this is the construction you are looking for as well?
So instead of:
if (condition) {
do {
condition = update(something);
} while (condition);
} else {
loop_never_taken(something);
}
I could write:
while (condition) {
condition = update(something);
} otherwhile {
loop_never_taken(something);
}
It's definitely shorter, and I would find it much clearer to read. It even translates easily into (pseudo) assembly:
while: test condition
bz elsewhile
loop: push something
call update
test: test condition
bnz loop
jmp done
elsewhile: push something
call loop_never_taken
done: ...
I feel like it's a basic enough structure that it deserves a little more sugar. But apparently there haven't been any successful language designers who rely on this structure as much as I do. I wonder how much I should read into that!

Resources