Typed stories

Braindump, journal, functional programming ..

Read this first

Testing Hydra

Install PostgreSQL. On NixOS, you need to configure configuration.nix with authentication = "local ..." and switch to root before running psql postgres.

Then follow the instructions here to get Hydra (add channel, install, set environment variables etc).

hydra-create-user to make an admin role, then run sudo hydra-server. Go to http://localhost:3000.

View →


Nix & Haskell

Creating shell.nix

$ nix-shell -p cabal2nix
[nix-shell:~/Werk/foo]$ cabal2nix --shell . > shell.nix

Running tests

[nix-shell:~/Werk/sfoo]$ runhaskell -isrc -itest test/Spec.hs 

Building

$ cabal2nix . > default.nix
$ echo "let pkgs = import <nixpkgs> {}; in pkgs.haskellPackages.callPackage ./default.nix {}" > build.nix
$ nix-build build.nix
$ ./result/bin/foo

For disabling tests in dependencies, I added the following to ~/.nixpkgs/config.nix:

{
  packageOverrides = super: let self = super.pkgs; in
  {
    noTestsHaskellPackages = self.haskellPackages.override {
      overrides = self: super: {
        mkDerivation = args: super.mkDerivation (args // {
          doCheck = false;
        });
      };
    };
  };
}

Continue reading →


Having some fun (and pain) with generics

Decided to try and wrap my head around generic programming and ended up sinking too much time trying to understand (or not?) some of the basic ideas. Just for fun, I tried to think how it would be possible to go from a homogenous list back to possibly a data structure.

module Foo where

import           Data.Maybe
import           Generics.SOP
import           Generics.SOP.TH

data Foo = F String Int
  deriving (Eq, Show)

deriveGeneric ''Foo

homoLstToFoo :: [String] -> Maybe Foo
homoLstToFoo xs
  = case iterP homoP of
      Nothing -> Nothing
      Just ps -> Just $ (to . SOP . Z) ps
  where
    homoP :: xs ~ [String, String] => Maybe (NP (K String) xs)
    homoP = fromList xs

    iterP :: Maybe (NP (K String) xs) -> Maybe (NP I '[String, Int])
    iterP mLst = case mLst of
      Nothing -> Nothing
      Just (x :* y :* _) -> case readMay (unK y) :: Maybe Int of
        Just z ->
...

Continue reading →


Lucid: Conditional rendering

I have a form written in Lucid and I need to add a prompt to the user based on some condition:


someForm :: Bool -> Html ()
someForm condition = body_ $
  ...
  renderIfCondition
  where
    renderIfCondition 
      | condition = div_ $ p_ [] "Some prompt message"
      | otherwise = ...

The question was what do I place in the otherwise clause. Initially, as a placeholder, I wrote

otherwise = makeElement "div" mempty

which when rendered, displayed an empty div. That worked (sort of) but was not ideal. If I didn’t have something to say, then there should be nothing. After looking through Lucid.Base, I found

instance Monad m => Monad (HtmlT m) where
  return a = HtmlT (return (mempty,a))
  ...

So my renderIfCondition becomes

renderIfCondition
   | condition = ...
   | otherwise = return () 

Continue reading →


When linking goes wrong

I have a Haskell application that needs to be deployed to a server. I took the route of having CircleCI copy the binary after stack install to a S3 bucket, and have an Ansible playbook that copies the binary to the server and launch it with Upstart. (which I thought routine, having deployed a few apps this way)

Except that the app didn’t quite run. Looking at the upstart logs

...
error while loading shared libraries: libmysqlclient.so.20: cannot open shared object file: No such file or directory

It’s fair to note at this point that all machines were on the same Ubuntu distro, and the obligatory aptitude install libmysqlclient-dev was run on all of them: local, CI and server. After reading up a bit on linking and checking the shared libraries on each server, it seems that Circle had libmysqlclient.so.20 installed because they had packages/programs that relied on it.

To get around the...

Continue reading →


Using coerce in Haskell

I recently worked on adding CSRF checks to a form.

module Csrf (
  Token
, ...
) where

newtype Token = MkToken String
  deriving (Eq, Show)

mkTokens :: [String] -> [Token]
mkTokens = map MkToken
-- ... rest of code

While newtype comes with no run-time costs, we do encounter some costs if we dealt with converting a list of strings to tokens. I chanced upon Safe Zero-cost Coercions for Haskell, which describes safe coercions for removing this overhead.

mkTokens :: [String] -> [Token]
mkTokens = coerce

See: Coercible

View →


Hspec: Skipping tests

I have some acceptance tests that I only want to run locally (i.e. skip them in the CI). when :: Applicative f => Bool -> f () -> f() from Control.Monad allows for conditional execution of Applicative expressions, so I can do something like

module FooSpec where

spec :: Spec
spec = do
  devMode <- runIO isDevMode
  when devMode $ describe "foobar" $ using chrome ...

isDevMode :: IO Bool
isDevMode = getEnvDefault ..

View →