Moving
I'm moving to http://maiz.tumblr.com/
I'm moving to http://maiz.tumblr.com/
I'm currently studying haskell's Parsec library. The main difference between Parsec and C's Yacc you need to be aware of is that in Parsec there is no gap between the syntactic rules - the grammar - and the actual use of it. It's all done with regular <awesome> haskell code.
So let's play. First, I'll need to parse a simple number.
First of all, I need to import Parsec (import Text.ParserCombinators.Parsec). Then, I create a number "rule", explaining what is a number. My explanation is in fact flawed (00000 is not a number) but I'll keep it this way for simplicity's sake. First I say what is the type of my rule. It's number :: Parser Integer. This means I'll write in it some monadic parser code, and spit out an integer. Don't worry if you don't know what "monadic" means. No one really gets it. For our purposes you can think about it as "lines of code inside a do statement".
The oneOf function (oneOf "0123456789") means that it will match a "0", or a "1", or a "2", and so on 'till "9". This is like regex's [0-9]. The many function, as the name makes clear, will match any quantity of the things passed to it. So in our case, it will match one or more characters from 0 to 9. It will match as many as it finds (greedy). In the end, I associate the result of this match to the variable "n" (n <- many (oneOf "0123456789") and return it as a number (return (read n)).
Let's test it. Open ghci and load the file. I'll call it operation.hs.
$ ghci
Prelude> :l operation.hs
[1 of 1] Compiling Main ( operation.hs, interpreted )
Ok, modules loaded: Main.
Now, we'll use the Parsec's parseTest helper function:
*Main> parseTest number "9"
9
parseTest number "04040"
4040
As you can see, our program is capable of receiving a number string input and returning an evaluated number. Yeah, I admit it is not that impressive. So let's move on. Now, I'll think about operators. Let's use just operators that can work easily with Integers, like plus (+), minus (-), mult (+) and power (^).
The definition of it is really simple. An operator is a char (operator :: Parser Char). It is one of "+", "-", "*" or "^" (o <- oneOf "+-*^"). And it returns the character matched (return (o)). Let's reload the file and test it:
Main> :l operation.hs
[1 of 1] Compiling Main ( operation.hs, interpreted )
Ok, modules loaded: Main.
*Main> parseTest operator "+"
'+'
*Main> parseTest operator "-"
'-'
*Main> parseTest operator "&"
parse error at (line 1, column 1):
unexpected "&"
As you can see here, it will just match what we told it to match. If we pass "&" to it, it will explode (but the error messages are really helpful).
Now we're getting in the cool part: operations. Operations are, basically, numbers interspersed with operators, like "1+2", "5^2" or "1+2*3-8". In our example, I'll deal only with operations with one operator.
Obviously, the type of operation is Parser Integer, since operating integers will always return an integer unless we use division (and we're not). The code is quite self explanatory. We have a number, that we call "n1" (n1 <- number), then we have an operator that we call "o" (o <- operator), and finally we have another number, that we call "n2" (n2 <- number). And we'll return the result of the function runop passing the operator and the numbers. But we don't have this function yet. So I'll do it using haskell's pattern matching:
The runop function receives a char and two integers and spits out an integer. Its implementation doesn't need more comments. Now we can see if all things hang out together.
Main> :l operation.hs
[1 of 1] Compiling Main ( operation.hs, interpreted )
Ok, modules loaded: Main.
*Main> parseTest operation "13-26"
-13
*Main> parseTest operation "2+31"
33
*Main> parseTest operation "4*5"
20
*Main> parseTest operation "5^2"
25
Yeah. Thing are fine. Here is the full code:
This example is very very simple. It will not handle operations like "1+2*8", it doesn't allow the use of spaces nor parens. It also can't have state and workout the value of variables, like in "1+x". This is what we're going to see soon.
Nice hum?
Connecting to mongohq with Haskell is really simple.
1. Create yout account at https://mongohq.com2. Install mongodb via cabal:cabal install mongodb 3. Check this code:This connects, logs in, inserts and then retrieves a document in a collection. Runnin' main will print something like this: