||4 years ago|
|src||4 years ago|
|.gitignore||4 years ago|
|ChangeLog.md||4 years ago|
|LICENSE||4 years ago|
|README.md||4 years ago|
|Setup.hs||4 years ago|
|default.nix||4 years ago|
|demobot.cabal||4 years ago|
|release.nix||4 years ago|
|shell.nix||4 years ago|
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.
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
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
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
src/Bot ├── DSL │ ├── Network.hs │ ├── State.hs │ └── Time.hs ├── DSL.hs ├── Extension.hs ├── Lib.hs └── Log.hs
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.