Skip to content


Switch branches/tags

Name already in use

A tag already exists with the provided branch name. Many Git commands accept both tag and branch names, so creating this branch may cause unexpected behavior. Are you sure you want to create this branch?

Latest commit


Git stats


Failed to load latest commit information.
Latest commit message
Commit time


This is a command-line utility that accepts an address and hits a few APIs: positionstack to get address coordinates, and to get a forecast for the coordinates. It dumps out the forecast for the next few days in a table format. It tries to use a cached copy of the forecast JSON stored for the given address if it exists and we're still within the timestamp window, otherwise it will try to look the forecast data up by hitting external APIs. This often succeeds.


You'll need to get an API access key from positionstack, which is free for the most basic level, but does require an account. For they require that you pass them your email address in the header, which this app takes care of if you provide it with your email address.

The configuration is in config.dhall, and hopefully is pretty obvious: the API key goes in positionStackAccessKey, and your email address goes in emailAddress.

Development Notes

This is not really meant to be the utility which you reach for when you need to check the weather, although it works...fine for that.

Rather, I wrote this to try to explore a few different concepts in Haskell, among them how to cleanly manage a bunch of effectful code--but at a small scale that is easy to wrap your head around. So I hope it is also useful for others as a simple example of how to do some basic, useful things in Haskell.

I've tried to push commits that both work independently as well as illustrate different stages of development. Right now here's what I've done:

  1. The first commit is a single file, uses the Req Monad provided with the req library as its base, and is pretty hacky (compared to the still-hacky later versions at least), with a lot of coupled up logic, partial functions, and generally messy code.

  2. Version 2 is largely just a refactoring of the first version to clean up the main application logic. It also improves somewhat on the caching logic (it's still pretty basic though).

  3. Version 3 splits the single file logic up into modules to better isolate concerns, adds a separate configuration file via dhall, and introduces a custom app monad instead of using the Req monad. This last change was done so that we can include the configuration via MonadReader, rather than hard-coding values into functions (in particular the API request calls which require configuration). It also opens the door to configuring stuff like the cache file and cache settings, retry settings for API calls that fail (cough cough), and more.

I hope to continue modifying this code, augmenting it, and improving it. In particular the Forecast.Request module needs some work to eliminate partial functions and tighten things up a bit. There should be some exception handling in place as well. I'd also like to try other approaches to overall structure than the "vanilla mtl" represented here, like the handle pattern as well as an effect system library like fused-effects. So, there is more to come.

Feedback is welcome!

Copyright 2020 Dave Della Costa, BSD 3-Clause "New" License


simple forecast cli app using web APIs







No releases published


No packages published