The fn package

This is a package candidate release! Here you can preview how this package release will appear once published to the main package index (which can be accomplished via the 'maintain' link below). Please note that once a package has been published to the main package index it cannot be undone! Please consult the package uploading documentation for more information.



A Haskell web framework where web handlers are just plain functions that return IO and parameters are typed arguments.

#!/usr/bin/env stack
-- stack --resolver lts-3.10 --install-ghc runghc --package fn
{-# LANGUAGE OverloadedStrings #-}
import Data.Monoid ((<>))
import Data.Text (Text)
import Network.Wai (Request, defaultRequest, Response)
import Network.Wai.Handler.Warp (run)
import Web.Fn

data Ctxt = Ctxt { _req :: Request }
instance RequestContext Ctxt where
  getRequest = _req
  setRequest c r = c { _req = r }

initializer :: IO Ctxt
initializer = return (Ctxt defaultRequest)

main :: IO ()
main = do ctxt <- initializer
          run 3000 $ toWAI ctxt site

site :: Ctxt -> IO Response
site ctxt = route ctxt [ end                        ==> indexH
                       , path "echo" /? param "msg" ==> echoH
                       , path "echo" // segment     ==> echoH
                  `fallthrough` notFoundText "Page not found."

indexH :: Ctxt -> IO (Maybe Response)
indexH _ = okText "Try visiting /echo?msg=hello or /echo/hello"

echoH :: Ctxt -> Text -> IO (Maybe Response)
echoH _ msg = okText $ "Echoing '" <> msg <> "'."

Provided you have stack installed, you can run this example like a shell script.

Fn lets you write web code that just looks like normal Haskell code.

The name comes from the fact that Fn emphasizes functions, and has no Fn monad (necessary context, as well as parameters, are passed as arguments, and the return value, which is plain-old IO, specifies whether routing should continue on).

[Skip to ReadMe]


Dependenciesbase (>=4.7 && <5), blaze-builder, bytestring, http-types, text, wai (>=3), wai-extra (>=3) [details]
Copyright2015 Daniel Patterson
AuthorDaniel Patterson <>
Home page
Source repositoryhead: git clone
UploadedThu Nov 5 21:28:36 UTC 2015 by DanielPatterson




Maintainers' corner

For package maintainers and hackage trustees

Readme for fn-

Fn (eff-enn) - a functional web framework.

Or, how to do away with the monad transformers, and just use plain functions.


See the example application in the repository for a full usage, but a minimal application is the following:

{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE TemplateHaskell   #-}

import           Control.Lens
import           Data.Monoid
import           Data.Text                (Text)
import qualified Data.Text                as T
import           Network.HTTP.Types
import           Network.Wai
import           Network.Wai.Handler.Warp
import qualified Network.Wai.Util         as W
import           Web.Fn

data Ctxt = Ctxt { _req :: Request

makeLenses ''Ctxt

instance RequestContext Ctxt where
  requestLens = req

initializer :: IO Ctxt
initializer = return (Ctxt defaultRequest)

main :: IO ()
main = do context <- initializer
          run 8000 $ toWAI context app

app :: Ctxt -> IO Response
app ctxt =
  route ctxt [ end ==> index
             , path "foo" // segment // path "baz" /? param "id" ==> handler]
    `fallthrough` notFoundText "Page not found."

index :: IO (Maybe Response)
index = okText "This is the index page! Try /foo/bar/baz?id=10"

handler :: Text -> Int -> Ctxt -> IO (Maybe Response)
handler fragment i _ = okText (fragment <> " - " <> T.pack (show i))