Write you some QuickCheck

Feb 8, 2016

In the next couple of posts, I’m going to implement a minimal version of QuickCheck from scratch. Follow along and you’ll:

I’ll be porting tons of Haskell code in F#2. — Disclaimer: I’ve done similar things in the past. It’s fun!

Here’s a list of posts to follow:


  1. This is advanced material. Basic knowledge of QuickCheck and property-based testing is assumed. If you’re in the beginning it’s fine! Read this post first by Scott Wlaschin, followed by this Pluralsight course by Mark Seemann, followed by these slides by Pedro Vasconcelos. There’s also this short intro as well.

  2. If you’re just looking for a production-ready QuickCheck based tool in F#, use FsCheck.

Those pesky build servers

Oct 8, 2015

Using a build server can actually hurt productivity:

  • It introduces a single point of failure
  • It can yield false-positives
  • It can yield false-negatives
  • It consumes time and energy to configure it properly

Think about it – you may not need a build server, after all.

It introduces a single point of failure

When things fail on the build server, it looks bad. It doesn’t matter if the build succeeds on the developer machines. – Seriously?

It can yield false-positives

The build might succeed on the build server, while fail on the developer machines. – Now what?

It can yield false-negatives

The build might fail on the build server for a whole lot of (unrelated) reasons to the build itself. Does that mean we’re screwed? – We might not.

It consumes time and energy to configure it properly

It’s one of those days where you end up spending more time getting the build server to work, than working on something else that’s probably more useful.

So…

Bring fun back to work:

  • Run the build on a few developer machines.
  • Report back whether it succeeds or not, and rely on that.

Get rid of those pesky build servers.

Regex-constrained strings with FsCheck

Sep 25, 2015

Source code available on GitHub.

Prelude

In Haskell, there’s the quickcheck-regex package, by Audrey (唐鳳) Tang, which allows to write and execute this:

generate (matching "[xX][0-9a-z]")
// Prints -> "''UVBw"

It exports a matching function that turns a Regular Expression into a DFA/NFA finite-state machine and then into a generator of strings matching that regex:

matching :: String -> Gen String

FsCheck

In F#, a similar generator for FsCheck can be written as:

let matching pattern =
    Gen.sized (fun size ->
        let xeger = Xeger pattern
        let count = if size < 1 then 1 else size
        [ for i in 1..count -> xeger.Generate() ]
        |> Gen.elements
        |> Gen.resize count)

The matching function uses the .NET port of dk.brics.automaton and xeger, and has the signature:

val matching : pattern:string -> Gen<string>

Use in F# Interactive

Here’s a way to generate regex-constrained strings with FsCheck in F# Interactive:

#r "../packages/Fare/lib/net35/Fare.dll"
#r "../packages/FsCheck/lib/net45/FsCheck.dll"

open Fare
open FsCheck

let matching pattern =
    Gen.sized (fun size ->
        let xeger = Xeger pattern
        let count = if size < 1 then 1 else size
        [ for i in 1..count -> xeger.Generate() ]
        |> Gen.elements
        |> Gen.resize count)

let generate = Gen.sample 1000 9

let a = generate (matching "[xX][0-9a-z]")
// val a : string list = ["X3"; "X1"; "x3"; "Xg"; "X7"; "xt"; "x5"; "xe"; "Xl"]

let b = generate (matching "\d{1,3}\.\d{1,3}\.\d{1,3}")
// val b : string list =
//  ["4.2.2"; "31.28.6"; "6.9.2"; "12.25.1"; "61.6.3"; "61.6.174"; "8.6.3";
//   "859.3.052"; "4.5.332"]

let c = generate (matching "^http\://[a-zA-Z0-9\-\.]+\.[a-zA-Z]{2,3}(/\S*)?$")
// val c : string list =
//  ["http://ng.EO-qzK8d8-o-2w.U1.-1-6-0793D-88t61.-Zk4K-crxu7L"+[222 chars];
//   "http://Xi-3SP6--K.VU";
//   "http://B96-4.-B..-..L.y.W4xDpM81...3Y.-BuR.Q8iZ.4-Aiv.---"+[101 chars];
//   "http://H.M.fQ..F.-dKYk.3.A-7.G-0rHIV--o81ft-h0G4sHBpx..-S"+[152 chars];
//   "http://55..-Zl33Pjh..97.b.9i1-e2y10..S1P-If.K-1KA-UW-O12L"+[108 chars];
//   "http://1L-3w..N22gftE2OI68.NU5.4F.D2jD43hG41DC.ATL...-r2V"+[66 chars];
//   "http://.3R8.-.-YJh3OP0MZgFn.l.Z.Zv..Y-wOy-.0P6j.-4Uyn7IB."+[167 chars];
//   "http://DD.1y54-4Bb8oU2-.T3-kVVzTtYT..-o..IU.2J8lNHZ8p...j"+[126 chars];
//   "http://mwa7NSM-Y-Ly5w..LFF"]

let d = generate (matching "^[a-zA-Z''-'\s]{1,40}$")
// val d : string list =
//  ["pqVm"; "tX'iu'SyM'"; "Q''DU'''''or'''O"; "l'L'M''Ew'YH";
//   "'O'CV'''U'''S''h"; "'"; "OQgJ'G'fR"; "''VGHWmcUB'T"; "''P"]

Notice how FsCheck yields different results on each run:

let a = generate (matching "[xX][0-9a-z]")
let b = generate (matching "[xX][0-9a-z]")
let c = generate (matching "[xX][0-9a-z]")

// val a : string list = ["x2"; "xn"; "Xc"; "Xf"; "Xm"; "xv"; "x6"; "Xi"; "Xn"]
// val b : string list = ["x7"; "X9"; "X3"; "xv"; "xn"; "xk"; "xn"; "xv"; "xo"]
// val c : string list = ["X5"; "xj"; "X0"; "xw"; "xq"; "Xg"; "xj"; "xv"; "X6"]

That’s because matching takes the size of generated test data into account.

Use in FsCheck with xUnit.net

Finally, here’s a quantified property scenario using FsCheck with xUnit.net:

open Fare
open FsCheck
open FsCheck.Xunit
open System.Text.RegularExpressions

let matching pattern =
    Gen.sized (fun size ->
        let xeger = Xeger pattern
        let count = if size < 1 then 1 else size
        [ for i in 1..count -> xeger.Generate() ]
        |> Gen.elements
        |> Gen.resize count)

[<Property>]
let ``Turns a regex into a generator of strings matching that regex``() =
    let pattern = "^http\://[a-zA-Z0-9\-\.]+\.[a-zA-Z]{2,3}(/\S*)?$"
    let matches = Arb.fromGen (matching pattern)
    Prop.forAll matches (fun s -> Regex.IsMatch(s, pattern))

// Output:
//  Ok, passed 100 tests.
//
// 1 passed, 0 failed, 0 skipped, took 1.34 seconds (xUnit.net 1.9.2).

F# on Emacs with Spacemacs

Apr 25, 2015

While F# is first-class citizen in Visual Studio, there’s also support for text editors:

There's also support for MonoDevelop and Xamarin Studio, which are IDEs. See the Cross-Platform Development with F# for more details.

Beyond Visual Studio

In my experience so far, getting F# to work outside Visual Studio requires quite an effort.

There are always a couple of steps to be done, and basic knowledge of the target text editor is also assumed.

A flexible, easy way, with Spacemacs

I learned Spacemacs in a tweet by Chris Bowdon. Spacemacs is essentially an Emacs configuration.

Image

Emacs for Windows, is available. Unzip to a folder and run. – An .emacs.d folder is automatically created in ~/AppData/Roaming/, storing all Emacs settings.

Install Spacemacs

Open a Git Bash command prompt window:

# Backup any existing Emacs configuration.
mv ~/AppData/Roaming/.emacs.d ~/AppData/Roaming/.emacs.bak

# Clone Spacemacs in place of the old Emacs configuration.
git clone --recursive http://github.com/syl20bnr/spacemacs ~/AppData/Roaming/.emacs.d

Then, launch Emacs and Spacemacs will automatically load, installing all required packages. After that, Emacs must be restarted.

Enable F#

After opening Emacs, it should show ~/.spacemacs under Recent files. – Click on that file to open it.

Add F# as shown in the following diff-output:

diff --git a/.spacemacs b/.spacemacs
index d6cedae..a47936c 100644
--- a/.spacemacs
+++ b/.spacemacs
@@ -23,6 +23,7 @@
      ;; markdown
      ;; org
      ;; syntax-checking
+     fsharp
      )
    ;; A list of packages and/or extensions that will not be install and loaded.
    dotspacemacs-excluded-packages '()

Then hit CTRL+C & CTRL+C, and the Spacemacs layer for F# will install itself.

Screenshots

Image

Image

Image

Image

The F# projects shown in the above screenshots are Qaiain and DiamondFsCheck.

Setting up Haskell on Windows

Apr 15, 2015

Why do that and not use Haskell Platform instead?

From what I have experienced so far, Haskell Platform falls behind the latest GHC release, and ships with Packages that one might not need.

Essentially there are two things needed:

  • GHC – Haskell’s compiler and interactive environment.
  • Cabal – Haskell’s build system, which also doubles as a package manager.

GHC

  • Download GHC for Windows from here.
  • Extract GHC contents to a folder and add to PATH
  • \ghc-x.y.z\bin
  • \ghc-x.y.z\mingw\bin

Cabal

  • Download Cabal for Windows from here.
  • Extract Cabal executable to a folder, open a command prompt (cmd.exe) and execute:
  • cabal-x.y.z.exe install
  • cabal-x.y.z.exe update
  • Open a MSYS-compatible (e.g. Git Bash) shell and execute:
  • cabal-x.y.z.exe install cabal-install

In the beggining I was wondering what a MSYS-compatible shell is, but it turns out the shell offered by Git Bash will do fine.

I was also wondering what's the difference between Cygwin and MinGW and came across this great Q&A on Stack Overflow.

  • Delete cabal-x.y.z.exe (after cabal-install is completed successfully)
  • Add C:\Users\[YOUR USERNAME]\AppData\Roaming\cabal\bin to PATH

Did it work out?

Open a command prompt (cmd.exe) window or a Git Bash window and execute where cabal, which should print the path where cabal executable resides:

C:\Users\[YOUR USERNAME]\AppData\Roaming\cabal\bin\cabal.exe

In the same command prompt executing ghci should launch GHCi (Haskell’s interactive environment):

GHCi, version 7.8.4: http://www.haskell.org/ghc/  :? for help
Loading package ghc-prim ... linking ... done.
Loading package integer-gmp ... linking ... done.
Loading package base ... linking ... done.
>

To get the > character show up in the prompt, add the following to C:\Users\[YOUR USERNAME]\AppData\Roaming\ghc\ghci.conf:

:set prompt "> "

That’s it – Happy Haskell Programming!

subscribe via RSS