* Introduction Write a static analyzer for ruby. Used an existing parser for ruby called `ruby-parse`. `ruby-parse` can generate an AST in JSON format. This made the task of writing a ruby parser simpler: Haskell comes with a great JSON parser. So we just have to specify how to convert from the AST defined by `ruby-parse` to our own AST. * Implementation ** ADTs *** Purpose Defining an Abstract Syntax Tree (AST) for Ruby using Algebraic Data Types (ADTs). *** Example -- Value represents any JSON data (object, string, number, null, array) Args = Value Name = Value Block = [Definition] Definition = Module | Function | Send Namespace = [Name] Send = {args : Args, namespace : Namespace, name :: Name} Module = {name : Name, block : Block} Function = {name : Name, args : Args, block :: Block} *** Live coding Define `Function` ** Higher-order types Missing a good example here. ** Type classes *** Purpose Be able to concert unstructured JSON data into our ADT. *** Example Consider the class class FromJSON a where parseJSON :: Value -> Parser a It's saying that `a` is convertible from json if there is a function `parseJSON` that takes a (json) `Value` and returns a `Parser a`. `Parser a` can be thought of as a procedure for generating a value of type `a`. So for instance. The monomorphic type `Parser Function` is a procedure that generates a value of type `Function`: *** Live coding Define an instance for `FromJSON` for `Function`. Define an instance for `FromJSON` for `Definition`.