Mercurial > hg > ishara
changeset 27:5de03f77dae1
Added documentation about types and revised arrow type specifications.
author | samer |
---|---|
date | Sat, 19 Jan 2013 14:22:09 +0000 |
parents | 8f4a21082c45 |
children | 673b8e45d05a |
files | README.txt arrows/@afirst/afirst.m arrows/@agraph/agraph.m arrows/@aparallel/aparallel.m arrows/@arr/arr.m arrows/@arrf/arrf.m arrows/@arrow/arrow.m arrows/@arrow/construct.m arrows/@arrow/first.m arrows/@arrow/mkunit.m arrows/@aswitch/aswitch.m arrows/@erate/erate.m arrows/@loop1/loop1.m arrows/anull.m arrows/arrow_repl.m arrows/perm.m arrows/umgather.m arrows/with_arrow.m general/funutils/@thunk/thunk.m |
diffstat | 19 files changed, 140 insertions(+), 25 deletions(-) [+] |
line wrap: on
line diff
--- a/README.txt Sat Jan 19 13:09:31 2013 +0000 +++ b/README.txt Sat Jan 19 14:22:09 2013 +0000 @@ -39,4 +39,119 @@ * Type specification language + Since learning about Haskell many years ago, it has become my favourite language that + I never program in. One result of this is that I have gradually evolved a semi-formal + type specification language for Matlab functions and values, which I use in the function + header comment. The format of a type declaration is as follows: + <name> :: <type_spec>. + <type_spec> ::= <type> [~ '<description>'] + + <name> is a valid Matlab identifier, starting with an alphebetic character and + continuing with alphabetic or numeric characters or underscores. + <description> consists of any characters valid in Matlab single-quoted string, and + is intended as a place to insert arbitrary annotations in a structured way. + The various type constructors are defined as follows. Capital letters denote variables. + + Primitive types + + real - double or single precision floating point value + complex - double or single precision complex floating point value + nonneg - real number >=0 + int - integer + natural - integers starting at 0 or 1 + bool - true or false (Matlab allows 0 or 1) + string - Matlab string (array of characters) + A..B - Integers between A and B inclusive + A--B - Real numbers between A and B inclusive + [A] - Integers between 1 and A inclusive + [A,B,..] - Comma separated list of integers in 1..A, 1..B etc (used for array domains) + A|B - Non-discrimitated union, value of type A or B (not recommended to use if possible) + {A,B,C} - Value from the enumerated set, eg {0,1,2} is equivalent to 0..2 (also deprecated) + + Array types + + [D->R] - Array with domain (ie size) D and element type R + [D] - Array with domain D and real elements + {D->R} - Cell array with domain D and elements of type R + + Function types + + <type_list> -> <type_list> - A functional function (no side effects) with input and output types. + <type_list> => <type_list> - An action with side effects, with input and output types. + + <type_list> ::= <type_spec> [, <type_list>] + + Cells and tuples + + cells(A) - arbitrary length row array of cells (list) of type A, equivalent to {[1,N]->A} + cell {A1,..,AN} - 1xN cell array with exactly the give types, ie, a tuple + pair(A,B) - equivalent to cell {A,B}. + + Structures + + struct { <field_list> } - Structure with specified fields. + <field_list> ::= <name> :: <type_spec> [ ; <field_list> ] + + Options + + Options are an indefinite length list of trailing arguments specifying name-value pairs, + used to pass values of optional named arguments. Functions are expected to use default + values for named arguments not specified. Structures can be used to pass several names-value + pairs at once. + + options { <option_list> } - Abitrary length list of arguments specifying optional values + <option_list> ::= <option_spec> [ ; <option_list> ] + <option_spec> ::= <name> :: <type> [/<default_value>] [~'<description>'] + + Dependent types + + Dependent types are use for functions where the type some argument or return depends on + the *value* of one of the arguments. These are most useful when the size of a returned array + depends on the value of a numerical input. Specifying these types requires some way to bind the + value of an argument to a variable in the type specification, for which purpose a single colon ':' + is used. We revise the type specification definition as follows: + + <type_spec> ::= [<variable> :] <type> [~'<description'] + + For example, the matlab function eye has type: + + eye :: N:natural -> [[N,N]]. + + Which means that the first argument is a natural number with value N, the return value is + a square N-by-N array or real numbers. + + + Variable length argument and return lists + + This has been the least consistent part of the type language and has changed as the + language relaxed from its rather Haskellish beginning, where variable length argument + and return lists really don't fit, into a more Matlaby state. In particular, I've ended + up using Matlab's own concept of a 'comma separated list', as distinct from any kind of + array, to represent a list of argument or return types. + + A comma separated list is literally a sequence of things separated by commas, eg + A, B, C, D + such as those that appear in various places in Matlab code, eg, + [<list>] = f(1,<list>); + x = [<list>]; + y= x(<list>); + + If A is a cell-array containing N elements, ie A = { a1, a2, ..., aN } + then A{:} denotes a comma-separated list of its elements, ie + A{:} == A{1}, A{2}, ..., A{N} + So, if A and B are lists of types, eg A = { real, natural } and B = {[[2,2]], real }, then + A{:} -> B{:} <denotes> real, natural -> [[2,2]], real + ie, a valid function type. Similarly, + cell A == cell {A{:}} == cell {real, natural} == pair(real,natural) + + If a variable such as A is used in a type specification, and we wish to emphasise + the fact that A denotes a cell array or list of N types, then we can write A@typelist(N). + This is a bit clunky and is a hangover from a previous method of specifying argument + lists - perhaps it shoud be A@X, where X is any type of types (ie a *kind*), eg + + cells(type) - arbirary list of types + {[N]->type} - list of N types + + +
--- a/arrows/@afirst/afirst.m Sat Jan 19 13:09:31 2013 +0000 +++ b/arrows/@afirst/afirst.m Sat Jan 19 14:22:09 2013 +0000 @@ -1,7 +1,7 @@ % afirst - arrow that applies some arrow to first input and passes rest through % % afirst :: -% arrow(A:arglist(N),B:arglist(M),S), +% arrow(A@typelist(N),B@typelist(M),S), % L:natural ~'the number of extra inputs to pass through' % -> arrow([A,{[L]->type}], [B,{[L]->type}],S). %
--- a/arrows/@agraph/agraph.m Sat Jan 19 13:09:31 2013 +0000 +++ b/arrows/@agraph/agraph.m Sat Jan 19 14:22:09 2013 +0000 @@ -6,7 +6,7 @@ % fig :: handle / gcf ~'figure for this instance'; % autoflush :: boolean/1 ~'unit will call drawnow after every iteration' % } -% -> agraph(N) < arrow(_:arglist(N),{},_). +% -> agraph(N) < arrow(_@typelist(N),{},_). % % METHODS % autoflush :: agraph(_) -> boolean.
--- a/arrows/@aparallel/aparallel.m Sat Jan 19 13:09:31 2013 +0000 +++ b/arrows/@aparallel/aparallel.m Sat Jan 19 14:22:09 2013 +0000 @@ -1,8 +1,8 @@ % aparallel - Parallel application of arrows to multiple inputs % % aparallel :: -% arrow( A1:arglist(N1), B1:arglist(M1), C1) ~'arrow with N1 inputs, M1 outputs', -% arrow( A2:arglist(N2), B2:arglist(M2), C2) ~'arrow with N2 inputs, M2 outputs', +% arrow( A1@typelist(N1), B1@typelist(M1), C1) ~'arrow with N1 inputs, M1 outputs', +% arrow( A2@typelist(N2), B2@typelist(M2), C2) ~'arrow with N2 inputs, M2 outputs', % -> arrow( [A1,A2], [B1,B2],cell {C1,C2}) ~'arrow with N1+N2 ins, M1+M2 outs'. % % The list of inputs of the second arrow is concatenated to those
--- a/arrows/@arr/arr.m Sat Jan 19 13:09:31 2013 +0000 +++ b/arrows/@arr/arr.m Sat Jan 19 14:22:09 2013 +0000 @@ -1,12 +1,12 @@ % arr - Lift function to processing unit % % arr :: -% F:(A:arglist(N)->B:arglist(M)) ~'arbitrary function with N inputs and M outputs', +% F:(A@typelist(N)->B@typelist(M)) ~'arbitrary function with N inputs and M outputs', % options { % nargin :: natural / nargin(F); % nargout :: natural / nargout(F); % } -% -> arrow(A:arglist(N),B:arglist(M),empty). +% -> arrow(A@typelist(N),B@typelist(M),empty). % % The arr class is a class of arrows which simply apply an ordinary % Matlab function to the inputs to obtain the outputs. In many cases,
--- a/arrows/@arrf/arrf.m Sat Jan 19 13:09:31 2013 +0000 +++ b/arrows/@arrf/arrf.m Sat Jan 19 14:22:09 2013 +0000 @@ -1,11 +1,11 @@ % arrf - Creat functional arrow using a function factory % % arrf :: -% FF: (SZ -> (A:arglist(N)->B:arglist(M))) ~'function to create function from sizes', +% FF: (SZ -> (A@typelist(N)->B@typelist(M))) ~'function to create function from sizes', % N: natural ~'number of inputs', % M: natural ~'number of outputs', % options {} -% -> arrow(A:arglist(N),B:arglist(M),empty). +% -> arrow(A@typelist(N),B@typelist(M),empty). % % The type empty denotes the type of empty arrays, ie % the state of an arr arrow is always an empty matrix.
--- a/arrows/@arrow/arrow.m Sat Jan 19 13:09:31 2013 +0000 +++ b/arrows/@arrow/arrow.m Sat Jan 19 14:22:09 2013 +0000 @@ -3,7 +3,7 @@ % arrow :: % N:natural ~'number of inputs', % M:natural ~'number of inputs' -% -> arrow(T1:arglist(N),T2:arglist(M),_). +% -> arrow(T1@typelist(N),T2@typelist(M),_). % % The arrow(T1,T2,S) type denotes the type of an arrow with N inputs % and M outputs when T1 is a list of N types and T2 is list of M types.
--- a/arrows/@arrow/construct.m Sat Jan 19 13:09:31 2013 +0000 +++ b/arrows/@arrow/construct.m Sat Jan 19 14:22:09 2013 +0000 @@ -1,7 +1,7 @@ % construct - Instantiate live processing unit % % construct :: -% arrow(A:arglist(N), B:arglist(M), S) ~'the arrow to instantiate', +% arrow(A@typelist(N), B@typelist(M), S) ~'the arrow to instantiate', % {[N]->size} ~'the sizes of the inputs' % -> unit(A,B,S) ~'live processing unit structure'. % @@ -10,7 +10,7 @@ % values and functions for running the live processing unit. Its fields % are as follows: % -% unit(A:arglist(N),B:arglist(M),S) :== struct { +% unit(A@typelist(N),B@typelist(M),S) :== struct { % starting :: () -> action (); % stopping :: () -> action (); % dispose :: () -> action ();
--- a/arrows/@arrow/first.m Sat Jan 19 13:09:31 2013 +0000 +++ b/arrows/@arrow/first.m Sat Jan 19 14:22:09 2013 +0000 @@ -1,7 +1,7 @@ % first - Apply arrow to first input and pass through others % % first :: -% arrow(A:arglist(N),B:arglist(M)), +% arrow(A@typelist(N),B@typelist(M)), % L:natural ~'the number of extra inputs to pass through' % -> arrow([A,{[L]->type}], [B,{[L]->type}]). %
--- a/arrows/@arrow/mkunit.m Sat Jan 19 13:09:31 2013 +0000 +++ b/arrows/@arrow/mkunit.m Sat Jan 19 14:22:09 2013 +0000 @@ -5,7 +5,7 @@ % structure representing a live processing unit. % % mkunit :: -% arrow(_:arglist(N),_:arglist(M),S) +% arrow(_@typelist(N),_@typelist(M),S) % -> struct { % starting :: () -> action (); % stopping :: () -> action ();
--- a/arrows/@aswitch/aswitch.m Sat Jan 19 13:09:31 2013 +0000 +++ b/arrows/@aswitch/aswitch.m Sat Jan 19 14:22:09 2013 +0000 @@ -1,7 +1,7 @@ % aswitch - switching arrow % % aswitch :: -% arrow(A:arglist(N),B:arglist(M),S) +% arrow(A@typelist(N),B@typelist(M),S) % -> arrow([A,{box(arrow(A,B,S))}], B,S). % % The resulting arrow has N+1 inputs and M outputs. The last input
--- a/arrows/@erate/erate.m Sat Jan 19 13:09:31 2013 +0000 +++ b/arrows/@erate/erate.m Sat Jan 19 14:22:09 2013 +0000 @@ -1,6 +1,6 @@ % erate - Drive sub-arrow at event rate, ie when events arrive % -% erate :: arrow(A:arglist(N),B:arglist(M),S), +% erate :: arrow(A@typelist(N),B@typelist(M),S), % -> arrow(events(A), events(B),S). % % the type events(A) denotes a list of types where each
--- a/arrows/@loop1/loop1.m Sat Jan 19 13:09:31 2013 +0000 +++ b/arrows/@loop1/loop1.m Sat Jan 19 14:22:09 2013 +0000 @@ -3,7 +3,7 @@ % loop1 :: % N:natural ~'number of inputs for this arrow', % M:natural ~'number of outputs for this arrow', -% ({[N]->size} -> ([A:arglist(N), {S}] -> [B:arglist(M), {S}])) +% ({[N]->size} -> ([A@typelist(N), {S}] -> [B@typelist(M), {S}])) % ~'function to map input sizes to state transformer', % ({[N]->size} -> S0:S) ~'function to map size of input to initial state' % -> arrow(A,B,S) ~'arrow from A to B with state of type S'.
--- a/arrows/anull.m Sat Jan 19 13:09:31 2013 +0000 +++ b/arrows/anull.m Sat Jan 19 14:22:09 2013 +0000 @@ -1,6 +1,6 @@ % asink - Do nothing absorbing arrow % -% asink :: N:natural -> arrow(_:arglist(N),{},empty). +% asink :: N:natural -> arrow(_@typelist(N),{},empty). function a=asink(nin) if nargin<1, nin=1; end a=arr(@nop,'nargin',nin,'nargout',0);
--- a/arrows/arrow_repl.m Sat Jan 19 13:09:31 2013 +0000 +++ b/arrows/arrow_repl.m Sat Jan 19 14:22:09 2013 +0000 @@ -1,7 +1,7 @@ % arrow_repl - Instantiate arrow system and drop into REPL. % % arrow_repl :: -% arrow(_:arglist(N),_:arglist(M),S) ~'arbitrary arrow', +% arrow(_@typelist(N),_@typelist(M),S) ~'arbitrary arrow', % {[N]->size} ~'sizes of inputs' % options { % gui :: boolean/false ~'create Java GUI for viewables'
--- a/arrows/perm.m Sat Jan 19 13:09:31 2013 +0000 +++ b/arrows/perm.m Sat Jan 19 14:22:09 2013 +0000 @@ -3,7 +3,7 @@ % perm :: % N:natural ~'number of inputs', % P:[[M]->[N]] ~'permutation of inputs' -% -> arrow(_:arglist(N), _:arglist(M), empty). +% -> arrow(_@typelist(N), _@typelist(M), empty). % % This function creates an arrow whos outputs can % be copies of any of the inputs in any order.
--- a/arrows/umgather.m Sat Jan 19 13:09:31 2013 +0000 +++ b/arrows/umgather.m Sat Jan 19 14:22:09 2013 +0000 @@ -1,14 +1,14 @@ % umgather - Run a processing unit and collect multiple outputs % % ugather :: -% unit({}, A:arglist(K), _) ~'live processing unit with K outputs', +% unit({}, A@typelist(K), _) ~'live processing unit with K outputs', % T:natural ~'number of iterations to run (can be inf)', % options { % draw :: boolean/false ~'whether or not to call drawnow after each iteration'; % quiet :: boolean/false ~'whether or not to suppress progress messages'; % chunk :: natural/1 ~'print progress every chunk interations'; % } -% -> B:arglist(K) ~'collected outputs'. +% -> B@typelist(K) ~'collected outputs'. % % This function accepts the live processing unit associated % with an arrow (as created by with_arrow). The arrow must
--- a/arrows/with_arrow.m Sat Jan 19 13:09:31 2013 +0000 +++ b/arrows/with_arrow.m Sat Jan 19 14:22:09 2013 +0000 @@ -1,7 +1,7 @@ % with_arrow - Instatiate processing network and run a command against it % % with_arrow :: -% arrow(T1:arglist(N),T2:arglist(M),S), +% arrow(T1@typelist(N),T2@typelist(M),S), % Cmd:(unit(T1,T2,S) -> action R) ~'function to apply to live unit', % {[N]->size} ~'sizes of inputs', % options {
--- a/general/funutils/@thunk/thunk.m Sat Jan 19 13:09:31 2013 +0000 +++ b/general/funutils/@thunk/thunk.m Sat Jan 19 14:22:09 2013 +0000 @@ -1,8 +1,8 @@ -% thunk(B:arglist(M)) ~ a thunk is something that eventually yields M outputs +% thunk(B@typelist(M)) ~ a thunk is something that eventually yields M outputs classdef thunk properties (GetAccess=private, SetAccess=immutable) - head % :: (A:arglist(N) -> B | thunk(B)) - args % :: A:arglist(N) + head % :: (A@typelist(N) -> B | thunk(B)) + args % :: A@typelist(N) end methods % thunk - create delayed evaluation