This commit is contained in:
Mats Rauhala 2018-12-23 23:43:31 +02:00
parent ad7290e705
commit 092bde3987

69
README.md Normal file
View File

@ -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.