Posts

LTMT Part 3: The Monad Cookbook

Introduction The previous two posts in my Less Traveled Monad Tutorial series have not had much in the way of directly practical content. In other words, if you only read those posts and nothing else about monads, you probably wouldn't be able to use monads in real code. This was intentional because I felt that the practical stuff (like do notation) had adequate treatment in other resources. In this post I'm still not going to talk about the details of do notation--you should definitely read about that elsewhere--but I am going to talk about some of the most common things I have seen beginners struggle with and give you cookbook-style patterns that you can use to solve these issues. Problem: Getting at the pure value inside the monad This is perhaps the most common problem for Haskell newcomers. It usually manifests itself as something like this: main = do lineList That code generates the following error from GHC: Couldn't match type `IO String...

Announcing C◦mp◦se :: Conference

Since most of my content is about Haskell, I would like to take this opportunity to inform my readers of a new conference that I and the other co-organizers of the New York Haskell Meetup are hosting at the end of January. It's called C◦mp◦se, and it's a conference for typed functional programmers. Check out the website at http://www.composeconference.org/ . We recently issued a call for papers . I know it's short notice, but the deadline is November 30. If you have something that you think would be interesting to typed functional programmers, we'd love to hear from you. Along with the conference we'll also be having one day be a less formal hackathon/unconference. If you would like to give a tutorial/demo at the unconference, email us at info@composeconference.org.

Field Accessors Considered Harmful

It's pretty well known these days that Haskell's field accessors are rather cumbersome syntactically and not composable.  The lens abstraction that has gotten much more popular recently (thanks in part to Edward Kmett's lens package) solves these problems.  But I recently ran into a bigger problem with field accessors that I had not thought about before.  Consider the following scenario.  You have a package with code something like this: data Config = Config { configFieldA :: [Text] } So your Config data structure gives your users getters and setters for field A (and any other fields you might have).  Your users are happy and life is good.  Then one day you decide to add a new feature and that feature requires expanding and restructuring Config.  Now you have this: data MConfig = MConfig { mconfigFieldA :: [Text] } data Config = Config { configMC :: MConfig , configFieldX :: Text , configFieldY :: Bool }...

Haskell Best Practices for Avoiding "Cabal Hell"

DEC 2020 UPDATE: A lot has changed since this post was written.  Much of "cabal hell" is now a thing of the past due to cabal's more recent purely functional "nix style" build infrastructure.  Some of the points here aren't really applicable any more, but many still are.  I'm updating this post with strikethroughs for the points that are outdated. I posted this as a reddit comment and it was really well received, so I thought I'd post it here so it would be more linkable.  A lot of people complain about "cabal hell" and ask what they can do to solve it.  There are definitely things about the cabal/hackage ecosystem that can be improved, but on the whole it serves me quite well.  I think a significant amount of the difficulty is a result of how fast things move in the Haskell community and how much more reusable Haskell is than other languages. With that preface, here are my best practices that seem to make Cabal work pretty well for me in...

Implicit Blacklisting for Cabal

I've been thinking about all the Haskell PVP discussion that's been going on lately. It should be no secret by now that I am a PVP proponent. I'm not here to debate the PVP in this post, so for this discussion let's assume that the PVP is a good thing and should be adopted by all packages published on Hackage. More specifically, let's assume this to mean that every package should specify upper bounds on all dependencies, and that most of the time these bounds will be of the form " Recently there has been discussion about problems encountered when packages that have not been using upper bounds change and start using them. The recent issue with the HTTP package is a good example of this. Roughly speaking the problem is that if foo-1.2 does not provide upper bounds on it's dependency bar, the constraint solver is perpetually "poisoned" because foo-1.2 will always be a candidate even long after bar has become incompatible with foo-1.2. If lat...

Ember.js is driving me crazy

For the past few months I've been working on a project with a fairly complex interactive web interface. This required me to venture into the wild and unpredictable jungle of Javascript development. I was totally unprepared for what I would find. Soon after starting the project it became clear that just using JQuery would not be sufficient for my project. I needed a higher level Javascript framework. After a doing a little research I settled on Ember.js. The Zombie Code Apocalypse Ember was definitely a big improvement over straight JQuery, and allowed me to get some fairly complex UI behavior working very quickly. But recently I've run into some problems. The other day I had a UI widget defined like this: App.FooController = Ember.ObjectController.extend({ // ... }); App.FooView = Ember.View.extend({ // ... }); It was used somewhere on the page, but at some point I decided that the widget was no longer needed, so I commented out the widget's mar...

Haskell Web Framework Matrix

A comparison of the big three Haskell web frameworks on the most informative two axes I can think of. image/svg+xml DSLs Combinators Snap Happstack Yesod NS Some things dynamic Everything type-safe Note that this is not intended to be a definitive statement of what is and isn't possible in each of these frameworks. As I've written elsewhere , most of the features of each of the frameworks are interchangeable and can be mixed and matched. The idea of this matrix is to reflect the general attitude each of the frameworks seem to be taking, because sometimes generalizations are useful.