diff --git a/README.md b/README.md new file mode 100644 index 0000000..2beb68f --- /dev/null +++ b/README.md @@ -0,0 +1,69 @@ +# Bot framework + +We had a discussion at work on Haskells suitability for Flowdock bots. The +argument was that if we want contributors outside of our Haskell team, we can't +use Haskell for the bot. + +My counterargument was that Haskell allows you to write such code that we +present the beatiful pure core to the contributors, while keeping the ugly +side-effectful world on the edges. + +This repository is an initial test of the ideas I had during the argument. + +# Bot architecture + +## Bot library + +The core idea behind the architecture is having a tagless final (assuming I +understand this term) DSL specifying what the bot can do. It's then up to the +interpreter to figure out how to actually run the logic. I have separated the +library into two conceptual sections, **extensions** and **core bot features**. +All of the modules in the library should have Safe Haskell extension enabled. + +The extensions have a limited subset of tagless final interpreters available +for it. This is in comparison to the core bot functionality which has error +handling and networking features as well. The two feature sets are defined in +`MonadBot` and `MonadExtension` constraints. See [DSL.hs](src/Bot/DSL.hs) for +the functionalities. It is up to the core contributors to add more tagless +final monads if more features are needed for the extensions. + +Each extension is a type `Extension meta` which defines the actuator for the +extension of type `MonadExtension m => Request meta -> m (Maybe (Response +meta))`. You can read this type as a function from bot input into a possible +action (response). The meta field is just a interpeter specific (flowdock, irc, +slack) meta field which can contain for example event types or target channels. + +The core bot is defined in the [Lib.hs](src/Bot/Lib.hs) file. This +implementation isn't most likely a good production quality implementation, but +shows a somewhat robust and clean implementation of a bot main loop. The nitty +gritty details of the networking stack is delegated to the `MonadNetwork` +interpreter. This could be for example reading and writing from a socket in +case of IRC bot, or reading from a `TChan` and writing to http in case of +Flowdock. + +``` +src/Bot +├── DSL +│   ├── Network.hs +│   ├── State.hs +│   └── Time.hs +├── DSL.hs +├── Extension.hs +├── Lib.hs +└── Log.hs +``` + +## Demo application + +The demo application is just reading from stdin and writing to stdout. You can +see the interpreter implementation in the [AppM.hs](src/AppM.hs) module. All +the nitty gritty details of the protocol specific implementation is done in +this module. As a sidenote, the `MonadData` instance is not working, I didn't +bother adding a sqlite / acid-state / whatever dependency. + +Extensions are collected in the [Extensions.hs](src/Extensions.hs) file which +is just a list of extensions with a suitable meta-type. The actual extensions +are implemented in the [Extension](src/Extension) namespace. A [hello +world](src/Extension/Hello.hs) implementation is provided as an example. I have +tried having the set of ghc extensions on the extension modules as small as +possible.