25.10.2015 Views

Write You a Haskell Stephen Diehl

1kEcQTb

1kEcQTb

SHOW MORE
SHOW LESS

You also want an ePaper? Increase the reach of your titles

YUMPU automatically turns print PDFs into web optimized ePapers that Google loves.

-- Start of layout ( Column: 0 )<br />

fib :: Int -> Int<br />

fib x = truncate $ ( 1 / sqrt 5 ) * ( phi ^ x - psi ^ x ) -- (Column: > 0)<br />

-- Start of new layout ( Column: 2 )<br />

where<br />

-- Indented block ( Column: > 2 )<br />

phi = ( 1 + sqrt 5 ) / 2<br />

psi = ( 1 - sqrt 5 ) / 2<br />

e Parsec monad is itself parameterized over a type variable s which stands for the State layer baked<br />

into the monad allowing us to embed custom parser state inside of our rules. To adopt our parser to<br />

handle sensitive whitespace we will<br />

-- Indentation sensitive Parsec monad.<br />

type IParsec a = Parsec Text ParseState a<br />

data ParseState = ParseState<br />

{ indents :: Column<br />

} deriving (Show)<br />

initParseState :: ParseState<br />

initParseState = ParseState 0<br />

Inside of the Parsec the internal position state (SourcePos) is stored during each traversal, and is accessible<br />

inside of rule logic via getPosition function.<br />

data SourcePos = SourcePos SourceName !Line !Column<br />

getPosition :: Monad m => ParsecT s u m SourcePos<br />

In terms of this function we can write down a set of logic that will allow us to query the current column<br />

count and then either succeed or fail to match on a pattern based on the current indentation level. e<br />

laidout combinator will capture the current indentation state and push it into the indents field in the<br />

State monad.<br />

laidout :: Parsec s ParseState a -> Parsec s ParseState a<br />

laidout m = do<br />

cur

Hooray! Your file is uploaded and ready to be published.

Saved successfully!

Ooh no, something went wrong!