Day 23: Fuzzy
Feeling fuzzy today. Posting any how, just to keep up the ritual.
Today’s Progress
Community
- Nice coffee chat, discussed community and music making.
- Delightful and thought provoking non-technical talks.
PLT
More time documenting and testing Alg
. It’s been a quite involved process. A
lot of the time has been devoted to developing a nice abstraction for the
testing harness, which will hopefully expedite completion on the rest of the
library.
I’ve made two decisions in the implementation that I’m fairly pleased with for the moment.
First, each specification of an algebraic structure includes a module called
Law
that defines predicates expressing the laws that should hold for
implementations of that structure. E.g., here is the signature for the Law
module for Functor
(** [Law] notes the laws that should be obeyed by any instantiation of {{!module-type:S} Functor} in the form of predicates that should be true for any arguments of the appropriate type. You can use {!module:Alg_qcheck.Functor} to generate property based tests of these laws for new modules satisfying this interface. @param F An implementation of a {{!module-type: S} Functor} *) module Law (F : S) (** *) : sig (** [identity x]: [F.map ~f:Fun.id x = Fun.id x] *) val identity : 'a F.t -> bool (** [composition f g x]: [F.map ~f:(f % g) x = (F.map ~f % F.map ~f:g) x] where [%] is composition. *) val composition : ('a -> 'b) -> ('c -> 'a) -> 'c F.t -> bool end
This is generating decent documentation that is quite tightly coupled with the code. It also gives the user predicates they can use for testing their implementations in ad hoc ways.
Second, I have been building out an auxiliary library Alg_qcheck
that
generates QCheck
property based tests of all a structure’s laws.
Here is what it looks like when using the library to generate tests for some
implementations of Functor
(note that the user has to supply a module that
includes the functor implementation together with a way of getting an arbitrary
value of that functor):
let functor_laws = let open Alg_qcheck.Functor in [ suite "Functor Laws for Option" (test (module struct include Alg.Functor.Option let arbitrary = option end)); suite "Functor Laws for List" (test (module struct include Alg.Functor.List let arbitrary = list end)); suite "Functor Laws for Array" (test (module struct include Alg.Functor.Array let arbitrary = array end)); ]
And the output of the tests:
[OK] Functor Laws for Option 0 Functor: Identity - [map id = id] for int. [OK] Functor Laws for Option 1 Functor: Identity - [map id = id] for int list. [OK] Functor Laws for Option 2 Functor: Composition - [map (f . g) = (map f) . (map g)] for int. [OK] Functor Laws for Option 3 Functor: Composition - [map (f . g) = (map f) . (map g)] for int list. [OK] Functor Laws for List 0 Functor: Identity - [map id = id] for int. [OK] Functor Laws for List 1 Functor: Identity - [map id = id] for int list. [OK] Functor Laws for List 2 Functor: Composition - [map (f . g) = (map f) . (map g)] for int. [OK] Functor Laws for List 3 Functor: Composition - [map (f . g) = (map f) . (map g)] for int list. [OK] Functor Laws for Array 0 Functor: Identity - [map id = id] for int. [OK] Functor Laws for Array 1 Functor: Identity - [map id = id] for int list. [OK] Functor Laws for Array 2 Functor: Composition - [map (f . g) = (map f) . (map g)] for int. [OK] Functor Laws for Array 3 Functor: Composition - [map (f . g) = (map f) . (map g)] for int list.
Tomorrow’s Program
PLT
Finish up documenting and testing [Alg], hopefully open a PR to publish the
package in the opam
repository.