Eben Kadile
Eben Kadile

Reputation: 779

How are apostrophes/character literals parsed in Haskell?

I'm trying to write something that reads Lambda expressions and outputs a beta reduced version. Lambdas will be typed as follows : \variable -> expression and applications will be of the form (expression) (expression). So if '\' is found at the beginning of the string it knows to process a Lambda and if '(' is found it knows to process an application.

I have a type for Lambda Expressions defined:

data Expression = Variable String
                | Lambda Expression Expression 
                | Apply Expression Expression 

Here's my first attempt at writing a function for reading the input

processInput :: String -> Expression
processInput ('\':input) = processLambda input
processInput ('(':input) = processApply input
processInput str         = Variable str

When I try to load this function I get

lexical error in string/character literal at ':'

So I tried using guards instead:

processInput input
    | head input == '\'                      = processLambda (tail input)
    | head input == '('                      = processApply (tail input)
    | otherwise                              = Variable input

But got

lexical error in string/character literal at character ' '

I have no idea what's wrong with either of these functions.

Upvotes: 2

Views: 1339

Answers (2)

sepp2k
sepp2k

Reputation: 370397

The backslash is a special character in string and character literals. You use to represent non-printable characters, line breaks and characters that would otherwise have special meaning in a literal. For example '\n' is a line break '\b' is a back space and '\'' is a single quote (without the \, the second ' would be seen as the end of the character literal).

So when you write '\', the lexer sees the start of a character literal, followed by an escaped '. Now it expects another ' to close the character literal, but gets a colon instead, causing the error.

To represent a backslash as a character literal, you escape the backslash with another backslash like this: '\\'.

Upvotes: 6

Chad Gilbert
Chad Gilbert

Reputation: 36385

The backslash is the escape character so it needs to be doubled up to represent a single backslash: '\\'.

processInput ('\\':input) = processLambda input
...

-- or...
processInput input
    | head input == '\\'                      = processLambda (tail input)
...

Upvotes: 2

Related Questions