Go to file
2018-12-23 23:43:31 +02:00
src Initial commit 2018-12-23 23:23:14 +02:00
.gitignore Initial commit 2018-12-23 23:23:14 +02:00
ChangeLog.md Initial commit 2018-12-23 23:23:14 +02:00
default.nix Initial commit 2018-12-23 23:23:14 +02:00
demobot.cabal Initial commit 2018-12-23 23:23:14 +02:00
LICENSE Initial commit 2018-12-23 23:23:14 +02:00
README.md Docs 2018-12-23 23:43:31 +02:00
release.nix Initial commit 2018-12-23 23:23:14 +02:00
Setup.hs Initial commit 2018-12-23 23:23:14 +02:00
shell.nix Initial commit 2018-12-23 23:23:14 +02:00

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 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 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 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 file which is just a list of extensions with a suitable meta-type. The actual extensions are implemented in the Extension namespace. A hello world implementation is provided as an example. I have tried having the set of ghc extensions on the extension modules as small as possible.