function [g,X]=history(X,fields,dim)
% history_extend - return state transformer that logs old state
%
% history_extend :: 
%    struct A         ~'any structure',
%    F:{[N]->string}  ~'list of field names',
%    natural          ~'dimension to cat along (defaults to 1)'
% -> (struct hist(A,F) ->struct hist(A,F)),
%    struct hist(A,F).
%
% struct hist(A,F) ~ 'structure A with history of fields F' ::= 
%    struct { 
%       A    ~'original fields from A'; 
%       history :: struct F ~ 'sub-struct containing fields F'
%    }.
%
% This function returns a state transformer function. The state MUST be
% a structure but it can have any fields. The history mechanism adds the
% field 'history' which contains the histories of certain fields from 
% the main structure. The returned function concatenates the current
% values of the named fields onto the end of the corresponding fields
% in the history, if X contains a field called 'cost', then
%
%   [logcost,X]=history(X,{'cost'},1);
%   Y=iterate(compose(logcost,update),X,'its',100);
%
% iterates the update function while maintaining a history of cost values.

	g=@logfields;
	if nargin<3, dim=1; end

	% prepare X to receive history
	if ~isfield(X,'history'), X.history=struct; end
	for i=1:length(fields)
		% initialise history fields if not present already
		if ~isfield(X.history,fields{i}),
			X.history.(fields{i}) = [];
		end
	end

	function X=logfields(X)
		for i=1:length(fields)
			field=fields{i};
			X.history.(field) = cat(dim,X.history.(field),X.(field));
		end
	end
end
	
	


