Understanding Triggers in NeoHaskell: A Gateway to Event-Driven Programming
Nick Tchayka
Posted on August 5, 2024
Since the release of NeoHaskell v0.3.0, we've noticed some confusion about what Triggers are and how they can be useful in real-world applications. In this post, we'll dive deeper into the concept of Triggers and explore their potential in various scenarios.
What are Triggers?
At their core, Triggers in NeoHaskell are entry points to your application where external agents can generate events in your service. They act as a bridge between the outside world and your application's event loop.
The Simplest Trigger: Time
Let's start with the simplest example we provided in our release notes:
tickTrigger :: Trigger TickEvent
tickTrigger = Time.triggerEveryMilliseconds 1000 (\_ -> Tick)
This Trigger generates a Tick
event in your application every 1000 milliseconds. While simple, it demonstrates the key concept: an external factor (in this case, the passage of time) is causing events to occur in your application.
Let's take a look at hypothetical triggers that could be implemented (they do not exist at the time of writing this, but they will be probably implemented in future versions).
Beyond Time: HTTP Servers
Triggers are far more powerful than just timers. Let's look at how they could be used to create an HTTP server:
postFooTrigger :: Trigger MyEvent
postFooTrigger = HTTP.trigger ANON
{ method = HTTP.POST,
route = "/foo",
handler = \_ -> MyEvent
}
In this example, we're creating a Trigger that listens for POST requests to the "/foo" endpoint. Whenever a request is received, it generates a MyEvent
in your application. This is how Triggers facilitate building HTTP servers: they provide a way for incoming HTTP requests to generate events in your application's event loop.
More Real-World Examples
Triggers aren't limited to just time and HTTP. Here are a few more examples to illustrate their versatility:
- Chat Bot:
discordMessageTrigger :: Trigger ChatEvent
discordMessageTrigger = Discord.onMessage \msg ->
NewMessage ANON { author = msg.author, content = msg.content }
This Trigger would generate a NewMessage
event every time a message is received in a Discord channel.
- File System Watcher:
fileChangeTrigger :: Trigger FileEvent
fileChangeTrigger = FileSystem.onChange "/path/to/watch" \change ->
FileChanged ANON { path = change.path, type = change.type }
This Trigger would generate a FileChanged
event whenever files in the specified directory are modified.
- Database Listener:
dbChangeTrigger :: Trigger DBEvent
dbChangeTrigger = Database.onUpdate "users" \update ->
UserUpdated ANON { id = update.id, fields = update.changedFields }
This Trigger would generate a UserUpdated
event whenever a record in the "users" table is updated.
Why Triggers Matter
Triggers are crucial because they allow your NeoHaskell application to react to the outside world in a structured, functional manner. They provide a clean separation between:
- How external events are received (the Trigger)
- How those events are represented in your application (the Event)
- How your application responds to those events (the Update function)
This separation makes it easier to reason about your application's behavior, test individual components, and modify or extend functionality over time.
Conclusion
Triggers in NeoHaskell are a powerful abstraction that enable truly event-driven programming. Whether you're building a simple CLI tool with a timer, a web server handling HTTP requests, a chat bot responding to messages, or a complex system reacting to database changes and file system events, Triggers provide a consistent, functional approach to handling external inputs.
We're excited to see what the NeoHaskell community builds with Triggers. If you have any questions or want to share what you're working on, join us on Discord or GitHub. Happy coding!
Posted on August 5, 2024
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.
Related
August 5, 2024