A Project in Haskell: One Week Apps by@james_32022
2,162 reads

A Project in Haskell: One Week Apps

Read on Terminal Reader

Too Long; Didn't Read

Company Mentioned

Mention Thumbnail

Coin Mentioned

Mention Thumbnail
featured image - A Project in Haskell: One Week Apps
James Bowen HackerNoon profile picture


James Bowen
react to story with heart

Lately we’ve focused on some of the finer points of how to learn Haskell. But at a certain point we want to actually build things. This next series of articles will focus on some of the more practical aspects of Haskell. This week, I’m going to introduce one of my own Haskell projects. We’ll first examine some of the reasons I chose Haskell. Then we’ll look at how I’ve organized the project and some of the pros and cons of those choices.

Introduction to One Week Apps

The program I’ve created is called One Week Apps (Names have never been my strong suit…I’m open to better ideas). It is designed to help you rapidly create mobile prototypes. It allows you to specify important elements of your app in a simple domain specific language. As of current writing, the supported app features are:

  1. Colors
  2. Fonts
  3. Alert popups
  4. Programmer errors (think NSError)
  5. Localized strings
  6. View layouts
  7. Simple model objects.

As an example, suppose you wanted to create an app from scratch and add a simple login screen. You’ll start by using the owa new command to generate the XCode project itself. First you'll enter some information about the app though a command line prompt. Then it will generate the project as well as some directories for you to place your code.

>> owa newCreating new OWA project!What is the name of your app:>> Blog ExampleWhat is the prefix of your app (3 letters):>> BEXWhat is the author's name:>> JamesWhat is your company name (optional):>> Monday Morning HaskellYour new app "Blog Example" has been created!

We then start specifying the different elements of our app. To represent colors, we’ll put the following code in a .colors file in the generated app directory.

Color labelColor  Hex 0x000000

Color fieldColor  Hex 0xAAAAAA

Color buttonColor  Blue 255  Red 0  Green 0

We can also specify some different fonts for the elements on your screen:

Font labelFont  FontFamily HelveticaNeue  Size 12.0  Styles Light

Font fieldFont  FontFamily Helvetica  Size 16

Font buttonFont  FontFamily Arial  Size 24  Styles Bold

Now we’ll add some localization to the strings:


Finally, we’ll specify the view layout itself. We can use the colors and fonts we wrote above. We can also modify the layout of the different elements.

View loginView  Type BEXLoginView  Elements    Label nameLabel      Text “NAME_TITLE”      TextColor labelColor      Font labelFont      Layout        AlignTop 40        AlignLeft 40        Height 30        Width 100    TextField nameField      PlaceholderText “NAME_PLACEHOLDER”      PlaceholderTextColor fieldColor      PlaceholderFont fieldFont      Layout        Below nameLabel 20        AlignLeft nameLabel        Height 30        Width 300    Label passwordLabel      Text “PASSWORD_TITLE”      TextColor labelColor      Font labelFont      Layout        Below nameField 40        AlignLeft nameLabel        Height 30        Width 100    TextField passwordField      PlaceholderText “PASSWORD_PLACEHOLDER”      PlaceholderTextColor fieldColor      PlaceholderFont fieldFont      Layout        Below passwordLabel 40        AlignLeft nameLabel        Height 30        Width 300    Button submitButton      Text “SUBMIT_BUTTON_TITLE”      TextColor buttonColor      Font buttonFont      Layout        Below passwordField 40        CenterX        Height 45        Width 200

Then we’ll run the owa gen command to generate the files. We need to add them manually to your XCode project (for now), but they should at least appear in the proper folder. Finally, we'll add a few simple lines of connecting code in the view controller:

class ViewController: UIViewController {

  override func loadView() {    view = BEXLoginView()  }...

And we can take a look at our basic view:

Rationale For Haskell

When I first came up with the idea for this project, I knew Haskell was a good choice. One major feature we should notice is the simple structure of the program. It has limited IO boundaries. We read in a bunch of files at the start, and then write to a bunch of files at the very end. In between, all we have is the complicated business logic. We parse file contents and turn them into algebraic data structures. Then we perform more transformations on those depending on the chosen language (you can currently use Objective C or Swift).

There is little in the way of global state to track (at least now when there’s no “compiling” occurring). There are no database connections whatsoever. Many of the things that can make Haskell clunky to deal with (IO stuff and global state) aren’t present in the main body of the program.

On the contrary, the body consists of computations playing to Haskell’s strengths. These include string processing, representing data abstractly, an so on. These were the main criteria for choosing Haskell for this project. Of course, there are libraries to deal with all the “clunky” issues I mentioned earlier. But we don’t even need to learn those for this project.


Now I’ll give a basic overview of how I architected this program. I decided to go with a multi-package approach. We can see the different packages here in my stack.yaml file:

packages:  - './owa-core'  - './owa-model'  - './owa-utils'  - './owa-parse'  - './owa-objc'  - './owa-swift'
  1. The model section contains the datatypes for the objects of the mobile app. Other packages rely on this.
  2. The parse package contains all code and tests related to parsing files.
  3. The objc package contains all code creating Objective C files and printing them out. It also has tests for these features.
  4. The swift package does the same for Swift code.
  5. The core package handles functionality like the CLI, interpreting the commands, searching for files, and so on.
  6. The utils package contains certain extra code needed by multiple packages.

Pro and Cons

Let’s look at some of the advantages and disadvantages of this architecture. As an alternative, we could have used a single-package structure. One advantage of the chosen approach is shorter compile time within the development cycle. There is a tradeoff with total compile time. Having many packages lead to more linking between libraries, which takes a while. However, once you’ve compiled the project once, each successive re-compile should take much less time. You’ll only be re-compiling the module you happen to be working on in most cases. This leads to a faster development cycle. In this case, the development cycle is more important than the overall compile time. If the program needed to be compiled from scratch on a deployment machine with some regularity, we might make a different choice.

The organization of the code is another important factor. It is now very obvious where you’ll want to add parsing code. If a feature seems broken, you know where to go to find a failing test or add in a new test to reproduce the bug. This system works far better than the haphazard version-based test organization I had earlier.

Another advantage I would list is it’s now a cleaner process to add another language to support. To support a new language, there will be few changes necessary to the core module. You’ll add another package (say owa-android) and add a few more options to Core. This should make it an easy repository to fork for, say, anyone who wanted to make an android version.

Let’s also consider some of the disadvantages. It is unlikely many of these packages will be used in total isolation from one another. The owa-parse module firmly depends on the owa-model package, for instance. The language specific modules will not interact with each other. But they're also not particularly useful unless you're using the parser anyways.

Additionally, the utils module is a real eyesore. It has a few random utilities needed by the testing code for several packages as well as the printing code. It seems to suggest there should only be one package for testing, but I find this to be unsatisfactory. It suggests instead there should be common printing code. It may be a reasonable solution to simply leave this code duplicated in certain places. This is another code-smell. But if different languages evolve separately, then their utility code might also.


So what did we learn about Haskell from this project? Haskell is great at internal processing. But programs with wide IO bounds can cause some headaches. Luckily, One Week Apps has lots of internal processing, but limited IO bounds. So Haskell was a natural choice. Meanwhile, multi-package organization has some advantages in terms of code organization. But it can also lead to some headaches as far as placing common code.

One Week Apps is now open source, so feel free to check it out on Github! Do you love the idea and think it would supercharge your app-writing? You should contact me and check out our issues page!

Want to contribute but have never touched Haskell? You’re in luck, because we’ve got a couple great resources for getting started! First, you should check out our Getting Started Checklist. It’ll walk you through some of the basic steps for installing Haskell. It’ll also show you some awesome resources to kickstart your Haskell code writing.

If you have a little experience but want more practice, you should download our Recursion Workbook. It’ll teach you about recursion, a fundamental functional paradigm. It also has some practice problems to get you learning!


. . . comments & more!
Hackernoon hq - po box 2206, edwards, colorado 81632, usa