└── README.md /README.md: -------------------------------------------------------------------------------- 1 | # Reason Projects Ideas 2 | 3 | This repo lists some of the stuff I personally find very compelled to build. Unfortunately I'm limited by time and energy (and skills, tbh), so I'm making this list in case anyone find these interesting. 4 | 5 | Feel free to contribute! 6 | 7 | ### https://github.com/0x00A/scratches for Reason 8 | 9 | ### https://gcc.godbolt.org for Native Reason (OCaml) 10 | 11 | ### [OCamlScope](http://camlspotter.blogspot.com/2013/06/ocamlscope-new-ocaml-api-search-by.html) or [Algolia](https://www.algolia.com) for the generated documentation 12 | 13 | Easier types search & search in general. 14 | 15 | ### Ppx macro that turns any function into a CLI command 16 | Reason (OCaml)'s function has all the features we want in a terminal tool's interface: 17 | - labelled arguments (which turn into CLI flags) with optional renaming (flag shortcut) 18 | - types, which turn `list string` into a CLI flag that accepts... a list of strings 19 | - optional arguments, with/without default value. 20 | - Doc block comments, to explain each parameter 21 | 22 | As a bonus, we get free manpage and shell autocomplete! 23 | 24 | ### Inline [power assert](https://github.com/power-assert-js/power-assert) 25 | Sometimes I don't really want full-blown unit tests. In addition to the guarantees the type system provides, I'd like to tackle on a few example use-cases for a function. Heck, some do this already in the form of comments. Jane Street's [Core_kernel](https://github.com/janestreet/core_kernel/blob/master/src/core_array.ml#L302) already does the inline part (not executed in production, naturally); I'd like that, but with power assert's crazy good-looking output. 26 | 27 | Examples are great. We'd also be able to extract these tests and display them in the API docs. 28 | 29 | ### [Jest](https://facebook.github.io/jest/)-like snapshot testing 30 | Jest's snapshot testing is really helpful. We might be able to leverage language-level concepts like marshalling (serializing the entire program, including closures) and pretty-printing through Format, to have almost free snapshot testing! 31 | 32 | ### API search by giving example input & output 33 | *See: http://www.wilfred.me.uk/blog/2016/07/30/example-driven-development*. Another one, built on top of types, would be Haskell's [Hoogle](https://www.haskell.org/hoogle/) and OCaml's very own [OCamlScope](https://github.com/camlspotter/ocamloscope). 34 | 35 | Given `"hello"`, what's the function that'll give me the output `"Hello"`? (`String.capitalize`). 36 | 37 | Naively, we'd iterate through all the functions in our database and execute each. This is expensive; a few optimizations: 38 | - filter by input and output type. This will reduce the search space by a huge amount 39 | - cache computation 40 | - restrict the input to a few values per type, e.g. "hello", "hi world", "" for strings 41 | - restrict the functions to a set of popular ones 42 | 43 | Furthermore, If the user provides `["hello", "world"]` as input and "hello world" as output, we'd filter down to `String.concat` and `outputHelloWorld` (random custom function), then allow the user to further filter down by another argument (e.g. `" "`, in order to get to `String.concat` here). 44 | 45 | ### `Obj.magic` to bypass the type checker temporarily 46 | Type `Obj.magic` type acts like an `any` type. We can have a special mode that annotates all of the values of a file as `Obj.magic`, and iterate like a dynamic language. 47 | 48 | ### [GraphQL type system](http://graphql.org/docs/typesystem/), using actual types 49 | GraphQL schemas are built like [this](http://graphql.org/blog/#building-the-graphql-schema). With ppx and OCaml's type system, we can generate the introspection tools through `type myShape = {foo: int}` rather than through an informal, hand-rolled type system a-la `let myShape = graphQLSchema ({field: "foo", type: "int"})`. 50 | 51 | ### Smart editor-agnostic templates 52 | Context: [language-server](http://langserver.org) has something called "code action"; upon seeing e.g. a type error, an editor can ask the server whether there's an automatic one-click fix. 53 | We can ~~abuse~~ leverage this capability to provide some editor snippets/templates, e.g. a boilerplate ReasonReact component. Here's the workflow (prepare to be mind blown): 54 | 55 | - User writes `[%%%React.reducer "MyComponent" foo bar];` 56 | - A corresponding ppx activates and transforms that into: `let a = pleaseRemoveThisLineAfterFillingTheTemplate; let component = ReasonReact.reducerComponent "MyComponent"; let make ::foo ::bar _children => ...;` 57 | - Aka, the ppx just scaffolds a component template _under the hood_ 58 | - Code action triggers because of a type error (`pleaseRemoveThisLineAfterFillingTheTemplate` is not found) 59 | - Click on code action to fix the problem; the language-server macroexpands the ppx and returns the inlined result. 60 | - User removes that offending line and fills the implementation details. 61 | 62 | Alternatively, it'd be nice if language-server comes with a code template system =). But this arguably contrived approach might help dissuading newcomers from using ppx too much. 63 | 64 | ### `[@@ocaml.deprecated]` as an API explorer 65 | `[@@ocaml.deprecated "use foo instead"]` can be attached to an expression so that the compiler will warn at dev time about the deprecated API. But we can use that to indicate something like: 66 | 67 | ```reason 68 | let log = "" [@@ocaml.deprecated "This is located under Js.log"] 69 | let consoleLog = "" [@@ocaml.deprecated "This is located under Js.log"] 70 | let consolelog = "" [@@ocaml.deprecated "This is located under Js.log"] 71 | ``` 72 | 73 | And let people explore which library contains which API they're trying to find. 74 | 75 | ### IReason 76 | 77 | [Jupyter Notebooks](http://jupyter.org), for Reason. There's already an [IOCaml notebook](https://github.com/andrewray/iocaml)! 78 | 79 | ### Shell-like syntax for reason 80 | Good for shell scripting! Also, check out [Shelljs](https://github.com/shelljs/shelljs). A Reason port would be great! 81 | 82 | ### Show the reified type info instead of the generic one 83 | Hovering over a value in an editor sometimes shows you the generic type rather than the specific one. For example: 84 | 85 | ``` 86 | let identity x => a; 87 | let a = 1; 88 | let b = identity a; 89 | ``` 90 | 91 | Hovering over `identity` will show the generic type signature `'a -> 'a`. Ideally, I'd like to see it in context: `int -> int`, with the actual, generic type also specified somewhere (in order not to mislead users). 92 | 93 | ### Automatic variable naming 94 | Once we start checking in the AST, we can have an easy config option for auto-naming some variable names based on their position in the syntax tree. While we're killing the debate about syntax and formatting, might as well kill the debate about naming things! 95 | 96 | ### README generator 97 | We already have ocamldoc and odoc for great documentation page generated from interface files. But those documentation often lack emphasis and usage demos (see https://github.com/noffle/art-of-readme). It'd be great if can let people mark some types, docblock comments, and unit tests as "important" and turn them into prominently displayed usage demos in the README. 98 | 99 | ### Themed documentation/code style 100 | 101 | [Odoc](https://github.com/ocaml-doc/odoc) generates documentation with overridable styles. On the web, while we're printing the code/doc in the person's favorite syntax, we might as well allow setting the entire style of the code/doc page. 102 | 103 | ### Javascript-to-(insufficiently typed)-Reason transpiler 104 | Using [Babel](http://babeljs.io) or [Flow](https://flowtype.org), parse JavaScript & translate it as much as possible to Reason. Then use the Reason formatter (refmt)'s [JSON import](https://github.com/facebook/reason/pull/724) to edit the Reason code until it's well-typed (alternatively, you could annotate everything as `Obj.magic` from above). 105 | 106 | It's basically a JS-to-Reason compiler, but one which requires much less work and a bit of manual intervention. That'd be one way of doing interop... 107 | 108 | ### Check in the AST 109 | Reason gets this closer than most languages. Check in the AST, diff using the AST, and reify the AST into a concrete syntax using the built-in `refmt`. No more syntax debates in the future: your visual preference stays local. Heck, nobody checks in their editor theme and mandates the whole team to use it, right? 110 | 111 | For those who want a pure AST editor, this is the transition step toward that idea. 112 | 113 | Once syntax becomes a personal preference, the printer's correctness becomes much less of a concern. Up until this point we needed very clear and deterministic rules on how things should print in our editor. In the future, maybe we can use some heavy lifting to print out the code using complicated heuristics learned from the coder's habit (machine learning? This *is* the far-fetched ideas section =)). 114 | 115 | ### Debugging experience 116 | OCaml has a time-traveling debugger! Right now it's full terminal-based and interacting with it requires a couple keystrokes too many for common actions. We can sugar coat it. 117 | 118 | ### Refactoring tool 119 | Some DSL like `re-factor "module Foo" "module Bar"`. `re-factor "module __A = {type t;}" "module __A = {type t2;}"`. 120 | 121 | 122 | ### Dev-time Function Instrumentation 123 | See https://github.com/mattphillips/babel-plugin-console 124 | 125 | --------------------------------------------------------------------------------