Singpolyma

Archive of "Haskell"

Archive for the "Haskell" Category

Error Handling in Haskell

Posted on

When I first started learning Haskell, I learned about the Monad instance for Either and immediately got excited. Here, at long last, was a good solution to the error handling problem. When you want exception-like semantics, you can have them, and the rest of the time it’s just a normal value. Later, I learned that the Haskell standard also includes an exception mechanism for the IO type. I was horrified, and confused, but nothing could have prepared me for what I discovered next.

While the standard Haskell exception mechanism infects all of IO it at least has a single, well-defined type for possible errors, with a small number of known cases to handle. GHC extends this with a dynamically typed exception system where any IO value may be hiding any number of unknown and unknowable exception types! Additionally, all manner of programmer errors in pure code (such as pattern match failures and integer division by zero) are thrown into IO when they get used in that context. On top of everything, so-called exceptions can appear that were not thrown by any code you can see but are external to you and your dependencies entirely. There are two classes of these: asynchronous exceptions thrown by the runtime due to a failure in the runtime itself (such as a HeapOverflow) and exceptions thrown due to some impossible-to-meet condition the runtime detects (such as detectable non-termination). Oh, I almost forgot, manually killing a thread or telling the process to exit are also modeled as “exceptions” by GHC.

Once the initial decision to have a dynamically typed exception system was made, everything that could make use of an exception-like semantic in any case was bolted on. What am I going to do, though? Write my own ecosystem and runtime that works how I would prefer? No, I’m going to find a way to make the best of the world I’m in.

When dealing with this situation, there are two separate and equally important things to consider: exception safety, and error handling. Exception safety describes the situation when you are, for example, acquiring and releasing resources (such as file handles). You want to be sure you release the resource, even if the exception system is going to abort your computation unceremoniously. You can never know if this will happen or not, since the runtime can just throw things at you, you always need to wrap resource acquisition/release paths in some exception safety. There are a lot of complex issues here, but it’s not the subject of this post so suffice to say the main pattern of interest for dealing with this is bracket.

Error handling is totally different. This is where you want to be able to recover from possible recoverable errors and do something sensible. Retry, save the task for later, alert the user that their request failed, read from cache when the network is down, whatever.

The first move in this area that I saw that I liked, was the errors package. Many helpers for dealing with error values, and in earlier versions a helper that would exclude unrecoverable errors and convert the rest to error values. I liked this pattern, but wanted more. This is Haskell! I wanted to know, at a type level, when recoverable errors had already been handled. Of course, programmer errors in pure code and unrecoverable errors from the runtime are always possible, so we can’t say anything about them at the type level, but recoverable errors we could know something about. So I wrote a package, iterated a few times, and eventually became a dependency for the helper in the errors package that I had based my whole idea on. Until very recently, errors and unexceptionalio were the two ways I was aware of to handle recoverable errors (and only recoverable errors) reliably, and know at a type level that you had done so. Recently errors decided to change the semantic to fit the previously-misleading documentation of the helper and so unexceptionalio now stands alone (to my knowledge) in this area.

In light of this new reality, I updated the package to make it much more clear (both in documentation and at a type level) what hole in the ecosystem this fills. I exposed the semantic in a few more ways so it can be useful even to people who don’t care about type-level error information. I also named the unrecoverable errors. Things you might want to be safe from, or maybe log and terminate a thread because of, but never recover from. For now, I call these PseudoException.

UnexceptionalIO (when used on GHC) now exposes four instances of Exception that you can use even if you have no use for the rest of the package: ExternalError (for things the runtime throws at you, asynchronously or not), ProgrammerError (for things raised from mistakes in pure code), PseudoException (includes the above and also requests for the process to exit), and SomeNonPseudoException (the negation of the above). All of these will work with the normal GHC catch mechanisms to allow you to easily separate these different uses for the exception system.

From there, the package builds up a type and typeclass with entry and exit points that ensure that values in this type contain no SomeNonPseudoException. The type is only ever used in argument position, all return types are polymorphic in the typeclass (implemented for both UIO and IO, as well as for all monad transformers in the unexceptional-trans package) so that you can use them without having to commit to UIO for your code. If you use the helpers in a program that is all based on IO still, it will catch the exceptions and continue just fine in that context.

Finally, the latest version of the package also exposes some helpers for those cases where you do want to do something with PseudoException. For exception safety, of course, there is bracket, specialized to UIO. For knowing when a thread has terminated (for any reason, success or failure) there is forkFinally, specialized to UIO and PseudoException. Finally, to make sure you don’t accidentally swallow any PseudoException when running a thread, there is fork which will ignore ThreadKilled (you assumedly did that on purpose) but otherwise rethrow PseudoException that terminate a thread to the parent thread.

This is hardly the final word in error handling, but for me, this provides enough sanity that I can handle what I need to in different applications and express my errors at a type level when I want to.

Haskell2010 Dynamic Cast

Posted on

This post is not meant to be a suggestion that you should use this code for anything. I found the exploration educational and I’m sharing because I find the results interesting. This post is a Literate Haskell file.

Programmers often mean different things when they say “cast”. One thing they sometimes mean is to be able to use a value of one type as another type, converting as possible.

We’ll use dynamic typing to allow us to check the conversions at runtime.

> module DynamicCast (DynamicCastable(..), dynamicCast, Opaque) where
> import Data.Dynamic
> import Data.Void
> import Control.Applicative
> import Control.Monad
> import Data.Typeable
> import Text.Read (readMaybe)
> import Data.Traversable (sequenceA)

But we don’t want to expose the dynamic typing outside of this module, in case people become confused and try to use a Dynamic they got from elsewhere. Really we’re just using the Dynamic as an opaque intermediate step.

> newtype Opaque = Opaque Dynamic

Types can define how they both enter and exit the intermediate representation. This both allows casting existing types to new types, but also can allow casting new types to existing types without changing the instances for those existing types.

> class (Typeable a) => DynamicCastable a where
> 	toOpaque :: a -> Opaque
> 	toOpaque = Opaque . toDyn
>
> 	fromOpaque :: Opaque -> Maybe a
> 	fromOpaque (Opaque dyn) = fromDynamic dyn

And finally the cast itself.

> dynamicCast :: (DynamicCastable a, DynamicCastable b) => a -> Maybe b
> dynamicCast = fromOpaque . toOpaque

Let’s see some examples.

We’ll say that Integer and simple lists (including String) represent themselves and define no specific conversions.

> instance DynamicCastable Integer
> instance (Typeable a) => DynamicCastable [a]

Int is represented however Integer represents itself.

Anything that can convert to Integer can convert to Int.

Any String that parses using read as an Int can also convert to an Int.

> instance DynamicCastable Int where
> 	toOpaque = toOpaque . toInteger
> 	fromOpaque o = fromInteger <$> fromOpaque o <|> (readMaybe =<< fromOpaque o)

And now

dynamicCast (1 :: Int) :: Maybe Integer
Just 1

dynamicCast (1 :: Integer) :: Maybe Int
Just 1

This is pretty obvious and boring, but perhaps it gives us confidence that this is going to work at all. Let’s try something fancier.

Void is the type with no inhabitants, so it can never be converted to.

> instance DynamicCastable Void where
> 	fromOpaque _ = Nothing

Either is represented as just the item it contains, and any item can be contained in an Either.

> instance (DynamicCastable a, DynamicCastable b) => DynamicCastable (Either a b) where
> 	toOpaque (Left x) = toOpaque x
> 	toOpaque (Right x) = toOpaque x
>
> 	fromOpaque o = Left <$> fromOpaque o <|> Right <$> fromOpaque o

And now

dynamicCast 1 :: Maybe (Either Int Void)
Just (Left 1)

dynamicCast 1 :: Maybe (Either Void Int)
Just (Right 1)

dynamicCast (Left 1 :: Either Int Void) :: Maybe Int
Just 1

Maybe is very similar, store the Just as the unwrapped value, and store Nothing as Void.

> instance (DynamicCastable a) => DynamicCastable (Maybe a) where
> 	toOpaque (Just x) = toOpaque x
> 	toOpaque Nothing = toOpaque (undefined :: Void)
>
> 	fromOpaque = fmap Just . fromOpaque

dynamicCast (Left 1 :: Either Int Void) :: Maybe (Maybe Int)
Just (Just 1)

To be able to cast the contents of a Functor, the possible failure also lives in the Functor, so we need a wrapper.

> newtype FunctorCast f a = FunctorCast (f (Maybe a))

> mkFunctorCast :: (Functor f) => f a -> FunctorCast f a
> mkFunctorCast = FunctorCast . fmap Just

> runFunctorCast :: FunctorCast f a -> f (Maybe a)
> runFunctorCast (FunctorCast x) = x

> runTraversableFunctorCast :: (Traversable f) => Maybe (FunctorCast f a) -> Maybe (f a)
> runTraversableFunctorCast = join . fmap (sequenceA . runFunctorCast)

> instance (Functor f, DynamicCastable a, Typeable f) => DynamicCastable (FunctorCast f a) where
> 	toOpaque = Opaque . toDyn . fmap toOpaque . runFunctorCast
> 	fromOpaque (Opaque dyn) = FunctorCast . fmap fromOpaque <$> fromDynamic dyn

runTraversableFunctorCast $ dynamicCast (mkFunctorCast ["1"]) :: Maybe [Either Void Integer]
Just [Right 1]

Making A Website With Haskell

Posted on

This is a guide to building simple webapps using Haskell (modelled after this article on a different framework). We will use:

  • WAI (Web Application Interface, and various utilty packages) for the backend
  • mustache2hs for templating
  • sqlite-simple for database access

Getting set up

There is a very useful utility for building Haskell called Cabal, which will allow you to track which versions of which dependencies you are using, and will tell you if they are not properly installed, etc. Create a project.cabal config file, like so:

name:            project
version:         0.1.0
cabal-version:   >= 1.8
category:        Web
copyright:       © 2013 Your Name
author:          Your Name <youremail@example.com>
maintainer:      Your Name <youremail@example.com>
stability:       experimental
synopsis:        My awesome todo-list app
homepage:        http://github.com/yourName/repoName
build-type:      Simple
description:
        A longer description of my awesome app

executable Main
        main-is: Main.hs

        build-depends:
                base == 4.*,
                http-types,
                wai,
                wai-util,
                wai-dispatch,
                yesod-routes,
                warp,
                text,
                path-pieces

source-repository head
        type:     git
        location: git://github.com/yourName/repoName.git

cabal configure will check that you have everything installed cabal build will build your project.

You may want to set up a Makefile, like so:

GHCFLAGS=-Wall -fno-warn-name-shadowing -XHaskell98 -O2

dist/build/project/Main: project.cabal dist/setup-config Main.hs
    cabal build --ghc-options="$(GHCFLAGS)"

dist/setup-config: project.cabal
    cabal configure

.PHONY: clean

clean:
    find -name '*.o' -o -name '*.hi' | xargs $(RM)
    $(RM) -r dist dist-ghc

Hello World

Save this as Main.hs:

module Main (main) where

import Network.Wai.Handler.Warp (run)
import Network.HTTP.Types (ok200)
import Network.Wai.Util (string)

main = run 3000 (\_ -> string ok200 [] "Hello, World!")

Now make and run it:

cabal build
dist/build/bin/Main

Go to http://localhost:3000 and you should see your Haskell site!

Routing

Our previous app gave the same response to every request. We will use the routeGenerator utility to create fast, compiled routes from a simple syntax:

cabal install route-generator

Add the following rule to your Makefile:

Routes.hs: routes
    routeGenerator -r -m Application $< > $@

You will want a file named routes with your routing information in it.

The router supports any possible HTTP method:

GET / => homePage
POST / => postPost
PURCHASE / => buyTheThing

Where the names on the right-hand side are the names of functions in your Application.hs module.

You can also capture parameters:

GET /post/: => showPost

Here’s an example of an Application.hs with handlers for these routes:

module Application where

import Network.HTTP.Types (ok200, notFound404)
import Network.Wai (Application)
import Network.Wai.Util (string)

homePage :: Application
homePage _ = string ok200 [] "Hello, World!"

postPost _ = string ok200 [] "You posted!"

buyTheThing _ = string ok200 [] "Bought it!"

showPost arg _ = string ok200 [] arg

on404 _ = string notFound404 [] "Not found"

And run the whole thing, with the proper 404, like so:

module Main (main) where

import Network.Wai.Handler.Warp (run)
import Network.Wai.Dispatch (dispatch)
import Application
import Routes

main = run 3000 $ dispatch on404 routes

Headers

Get a header:

import Network.Wai.Util (bytestring)
import Data.String (fromString)
import Data.Maybe (fromMaybe)
import Data.Monoid (mempty)

homePage req = bytestring ok200 [] (fromMaybe mempty $ lookup (fromString "User-Agent") $ requestHeaders req)

Set a header:

import Network.Wai.Util (stringHeaders')
homePage _ = string ok200 (stringHeaders' [("Content-Type", "text/calendar")]) "Not a calendar ;)"

Content types

Respond with the appropriate content type:

import Network.Wai.Util (handleAcceptTypes, string, json)

homePage = handleAcceptTypes [
        ("text/plain", string ok200 [] "You asked for text, here it is.")
        ("application/json", json ok200 [] ["A JSON", "array"])
    ]

Templates

There are many good templating systems. My favourites are blaze-html and mustache2hs, because:

  1. They give you some type-checking of your templates at compile time.
  2. They are super fast.

To use mustache2hs, first install it:

cabal install mustache2hs

You will need a module to contain the records that you will render out in your template (Records.hs):

module Records where

data HomePageData = HomePageData {
        title :: String,
        username :: Maybe String
    }

And an actual template to render (homePageView.mustache):

<html>
    <head>
        <title>{{title}}</title>
    </head>
    <body>
        <h1>{{title}}</h1>

        {{#username}}
            Welcome, {{username}}!
        {{/username}}
    </body>
</html>

Set up your Makefile to generate the code:

MustacheTemplates.hs: Records.hs homePageView.mustache
    mustache2hs -m Records.hs homePageView.mustache HomePageData > $@

And actually render it out:

import Network.Wai.Util (stringHeaders', textBuilder)
import MustacheTemplates

htmlEscape :: String -> String
htmlEscape = concatMap escChar
    where
    escChar '&' = "&amp;"
    escChar '"' = "&quot;"
    escChar '<' = "&lt;"
    escChar '>' = "&gt;"
    escChar c   = [c]

homePage _ = textBuilder ok200
    (stringHeaders' [("Content-Type", "text/html; charset=utf-8")])
    (homePageView htmlEscape $ HomePageData "My Title" Nothing)

Logging Requests

If you want to see a log of all requests on standard out, you’ll need to change Main.hs to use a middleware:

import Network.Wai.Middleware.RequestLogger (logStdoutDev)

main = run 3000 $ logStdoutDev $ dispatch on404 routes

Serving Static Content

If you want to serve a directory of static content alongside your app, you can use a fallback mechanisms from the wai-app-static package:

import Network.Wai.Application.Static (staticApp, defaultWebAppSettings)
import Filesystem (getWorkingDirectory)

staticRoot = staticApp . defaultWebAppSettings

main = do
    cwd <- getWorkingDirectory
    run 3000 $ dispatch (staticRoot cwd) routes

Or alternately use the middleware from wai-middleware-static:

import Network.Wai.Middleware.Static (static)

main = run 3000 $ static $ dispatch on404 routes

Sessions

Some apps need a way to store data between requests using cookies. wai-session is a package that provides a generic way of doing this, and has existing backends for in-memory storage, encrypted cookies, and tokyocabinet. The wai-session-clientsession package contains the backend for encrypted cookies:

module Main where

import Data.Default (def)
import Data.Maybe (fromMaybe)
import Data.String (fromString)
import qualified Data.Vault as Vault

import Network.Wai
import Network.Wai.Util (string)
import Network.Wai.Handler.Warp (run)
import Network.HTTP.Types (ok200)
import Control.Monad.Trans.Resource (ResourceT)

import Web.ClientSession (getDefaultKey)
import Network.Wai.Session (withSession, Session)
import Network.Wai.Session.ClientSession (clientsessionStore)

app session env = do
    u <- sessionLookup "u"
    sessionInsert "u" (show $ pathInfo env)
    string ok200 [] $ fromMaybe "Nothing" u
    where
    Just (sessionLookup, sessionInsert) = Vault.lookup session (vault env)

main = do
    session <- Vault.newKey
    store <- fmap clientsessionStore getDefaultKey
    run 3000 $ withSession store (fromString "SESSION") def session $ app session

Databases

For database access, use postgresql-simple or sqlite-simple:

import Database.SQLite.Simple (open, close, query, Only(..))
import Database.SQLite.Simple.FromRow (FromRow(..))

data Post = Post {
        postTitle :: String,
        postBody :: String
    }

instance FromRow Post where
    fromRow = Post <$> field <*> field

showPost :: Int -> Application
showPost postId _ = do
    conn <- open "./production.sqlite3"
    [post] <- query conn "SELECT * FROM posts WHERE post_id = ?" (Only postId)
    string ok200 [] (postTitle post)
    close conn

Of course, you shouldn’t probably re-connect on every request. Change your Makefile to have the router pass an argument through:

Routes.hs: routes
    routeGenerator -r -n 1 -m Application $< > $@

And do the connection from Main.hs:

import Database.SQLite.Simple (open, close)

main = do
    conn <- open "./production.sqlite3"
    run 3000 $ dispatch on404 (routes conn)
    close conn

And then you can use the connection:

showPost :: Connection -> Int -> Application
showPost conn postId _ = do
    [post] <- query conn "SELECT * FROM posts WHERE post_id = ?" (Only postId)
    string ok200 [] (postTitle post)

Deploying to Heroku

Deploying to Heroku is easy with the heroku buildpack.

First, our hello world app needs to change slightly. Heroku tells us what port to run on with the PORT env variable:

module Main (main) where

import System.Environment (getEnv)
import Network.Wai.Handler.Warp (run)
import Network.HTTP.Types (ok200)
import Network.Wai.Util (string)

main = do
    port <- fmap read $ getEnv "PORT"
    run port $ string ok200 [] "Hello, World!"

Then add a Procfile in your root dir to tell Heroku how to start your app:

web: ./dist/build/project/Main

And add a Setup.hs to build your app:

import Distribution.Simple
main = defaultMain

Then, assuming your project is a git repo:

heroku create --stack=cedar --buildpack https://github.com/pufuwozu/heroku-buildpack-haskell.git
git push heroku master

Compiling Mustache Templates

Posted on

Christopher Vollick and I were recently discussing ways to get more compile-time guarentees out of our web templates. We both love Mustache for its simplicity and its thin-view philosophy, so that was a natural place to start.

I decided to try writing a tool to convert Mustache templates to Haskell code, which I have done.

This allows the compiler to check a number of things for us including: ensuring we do not use any keys in the templates that are not defined in the model, ensuring that we do not use keys in the template in ways that are inconsistent with the datatype in the model, and ensuring that our partials and sections expect the context they will end up getting passed due to the structure of the templates.

It also gives us a speed boost. Comparing to the other popular Haskell Mustache implementation my current benchmarks show a significant speedup. This is to be expected, since GHC can perform optimisations that a runtime interpolator just can’t. Also, in order to be able to use arbitrary Haskell Records as context, runtime implementations have to perform runtime checks using a union type or the Typeable class. My implementation can do all these checks at compile time.

People familiar with Mustache may be wondering how I handle recursive partials, since this is a feature Mustache touts as being possible because the templates are not compiled. I make a compromise in my code: partials are rendered out as toplevel functions, just like any other file, and as such they only inherit the context directly above them, instead of inheriting the enitre scope all the way to the top. I rarely use values from higher scopes in my partials anyway, so I don’t think this is a very severe limitation.

Values that are displayed in the template must have an instance of Pretty from wl-pprint and values that are used in sections or inverse sections must either be lists of records (which get used as the context for the section body) or any Monoid instance. If the value (==mempty), it is considered falsey. Note that if you need values to be able to be optional, but want the natural mempty of your datatype to be truthy, you can acheive this by wrapping in a Maybe.

The requirement to be a Monoid is relaxed for Bool and a large list of numeric types, which get wrapped in the Any and Sum newtype wrappers by the code generator when they are detected in a record. This allows False and 0 to be treated as falsy for the majority of types where this would be interesting without needing to define orphan Monoid instances or wrap everything up in newtypes yourself.

There is example code on GitHub. Check it out, play with it, and let me know what you think!

Heterogenous Collections in Haskell

Posted on

One of the things statically typed languages like Haskell and C often don’t have great support for, is collections that contain elements that are not all of the same type. In a dynamically typed language one can store any element of any type in a collection, because the type is finally determined later when the value is used at runtime. With a statically typed language, the compiler wants to determine all the types at compile time, and so it often wants to force every element to be of the same time (homogeneous collections).

Normally when this problem arises, I find that I can rethink the problem in a way such that the solution does not require heterogeneous collections, but recently I’ve been working with one that, while I can solve it another way, the most natural solution seems to call for this.

The Haskell Wiki has a couple of suggestions for doing this. The easiest one, is just to use Data.Dynamic to do dynamic typing from inside Haskell. The problem with this is that it is both slower (the types of all values in the collection have to be checked at runtime) and less safe (if a bad value gets put in the data structure, it can cause the application to crash).

Another solution suggested there is exitstentially qualified datatypes. These solve the problem in a way that is safe (as long as you only need to perform operations from some typeclass on the data) and efficient, and is analogous to an upcast in a statically-typed Object-Oriented language. However, it can be a bit complex, and is a language extension.

A solution that will work in Haskell98 and give most of the benefits of exitstentially qualified datatypes (with less power) is to package up operations to be performed with the datatype, instead of the data itself. Any functions that you will want to call (such as those which are members of the typeclass you’re interested in) can be partially applied to the data, resulting in a function that is the exact same type as an equivalent function partially applied to some other instance of the same typeclass. You can thus put records full of these functions into a list or other collection, and it will work because they are all the same datatype. Then instead of calling (func x otherparams) you can just call (func otherparams) and get exactly the same result.

An example:

class SomeClass a where
	somefun :: a -> Int -> Bool

instance SomeClass Int where
	somefun = (>)

instance SomeClass [a] where
	somefun = (>) . length

data SomeFunAble = SomeFunAble {
		somefun_ :: (Int -> Bool)
	}

someFunAble :: (SomeClass a) => a -> SomeFunAble
someFunAble v = SomeFunAble (somefun v)

somelist = [someFunAble "hello", someFunAble (12::Int)]

otherlist = map (`somefun_` 12) somelist