category, package

13 views
Skip to first unread message

Serge D. Mechveliani

unread,
Apr 13, 2012, 3:05:42 PM4/13/12
to fricas...@googlegroups.com
I am sorry, may I ask, again, a question about categories and standard
constructors?
This time it is more concrete.
Concerning my request on adding categories to standard constructors
Waldek wrote

> Why do you need Integer (etc.) to have ParseCategory? You can have:
>
> ParseCategory(T : SetCategory) : Category == SetCategory with
> parseElem : String -> Product(T, String)
> [..]
>
> and then implement packages of that category.


1. I know what is "a domain of that category",
but what does this mean: "a package of that category" ?

2. Here is a concrete and small contrived example/question presented by
an Haskell program.

------------------------------------------------------------------------
class Show1 a where show1 :: a -> String
--
-- An user class for printing a data to String.
-- `Show1' is taken to avoid clash with `Show' of the standard library.

-- class <-> `category' of Spad,
-- `::' <-> `:' of Spad, `=' <-> `==', `:=', ':' <-> cons.
-- `a', `b' ... <-> category or a package parameter in Spad.
-- Integer, (,), [], Ratio are constructors from the standard library,
-- (a, b) <-> Product(a, b), [a] <-> List a, Ratio <-> Fraction.

instance Show1 Integer where show1 = show -- use the library function

instance (Show1 a, Show1 b) => Show1 (a, b) -- print pair
where
show1 (x, y) = concat["(", show1 x, "," show1 y, ")"]

instance Show1 a => Show1 (Ratio a) -- print fraction
where
show1 (n % d) = concat["(", show1 n, "/", show1 d, ")"]
-- contrived code

instance Show1 a => Show1 [a] -- print list
where
show1 [] = "[]"
show1 (x : xs) = concat [ "[", show1 x, showL xs, "]" ]
where
showL [] = ""
showL (x: xs) = concat ["," show1 x, showL xs]

data UPol a = UPol String [(a, Integer)]
--
-- An user data for an univariate polynomial over `a':
-- UPol <variable> <monomial list>,
-- a monomial is a pair (coefficient, exponent).

instance Show1 a => Show1 (UPol a)
where
show1 (UPol v mons) = concat [ "(UPol", v, show1 mons, ")" ]
--
-- mons is a list of pairs, and for this list the instance of
-- show1 is already defined.
------------------------------------------------------------------------

This is a contrived code, is has not been tried to compile.

Example of usage: the program

let f = UPol "x" [(1/1, 4), ((-1)/2, 3), (1/1, 0)]
:: UPol (Ratio Integer)
-- represents x^4 - (1/2)x^3 + 1
in show1 f

yields "(UPol x [(1%1,4),((-1)%2,3),(1%1,0)])"

This approach uses defining user class instances for the standard
domain constructors (,), [], Ratio.
And Haskell has not packages; probably, its polymorphic functions
(+ adding user instances to standard constructors) are sufficient.

Now, what is a reasonable code for this whole example with show1
(for Product, List, Fraction, UP) in Spad ?

ShowCategory(T : SetCategory) : Category == SetCategory with
show1 : T -> String
(`a' <-> T).
What packages to define to make show1 work as in the above example
in Haskell ?

Thanks.

------
Sergei
mec...@botik.ru

Serge D. Mechveliani

unread,
Apr 14, 2012, 2:15:52 AM4/14/12
to fricas...@googlegroups.com
On Fri, Apr 13, 2012 at 11:05:42PM +0400, Serge D. Mechveliani wrote:
> [..]

> Concerning my request on adding categories to standard constructors
> Waldek wrote
>
> > Why do you need Integer (etc.) to have ParseCategory? You can have:
> >
> > ParseCategory(T : SetCategory) : Category == SetCategory with
> > parseElem : String -> Product(T, String)
> > [..]
> >
> > and then implement packages of that category.
>
>
> [..]


I start to think now that this is by
(1) defining a Show category,
(2) defining an extended copy Integer1 for Integer, (**)
(3) defining a packge for each of the constructors
Integer1, Product, List, Fraction, UP,
(4) using further Integer1 instead of Integer.
Like this:

----------------------------------------------------------------------
INT ==> Integer

)abbrev category SHOW Show
Show() : Category == SetCategory with show : % -> String

)abbrev domain INT1 Integer1
Integer1() : Export == Implementation where

Export == Join(IntegerNumberSystem, ConvertibleTo String, OpenMath,_
Canonical, canonicalsClosed, Show)
Implementation == Integer add
Rep := INT
show(n : %) : String == convert(n) :: String

)abbrev package PAIR1 Pair1
Pair1(S : Show, T : Show) : Export == Implementation where
Pair ==> Product(S, T)
Export == with
show : Pair -> String

Implementation == add
show(p : Pair) : String ==
s := first p
t := second p
concat["(", show s, ",", show t, ")"]
...
----------------------------------------------------------------------

> show (construct(2,3) $ Product(INT1, INT1))

"(2,3)"

Is this what Waldek meant?

Thanks.

------
Sergei
mec...@botik.ru

Serge D. Mechveliani

unread,
Apr 16, 2012, 2:52:17 AM4/16/12
to fricas...@googlegroups.com


But, again, this approach does not help. Because
show(xs : List Product(INT1, INT1))

cannot derive Show for Product(INT1, INT1).

Bill Page wrote for the example of Sized:

> It is common to see in the Axiom library for example something like:
>
> )abbrev package SIZED Sized
> Sized(A:OrderedRing): with
> size: A -> Integer
> size: List A -> Integer
> size: DirectProduct(2,A) -> Integer
> == add
> size(a:A):Integer == abs(a)
> size(a:List A):Integer == reduce(+, map(size$SizedInt(A),a))
> size(a:DirectProduct(2,A)):Integer ==
> size(first a)$SizedInt(A) + size(second a)$SizedInt(A)
>
> Note: This code is just of illustration. I haven't actually tried to
> compile it.

But I do not see how this approach will work for the example with Show.

> You should study the code for interpret and especially the package
> InputFormFunctions1

I look into

InputForm():
Join(SExpressionCategory(String,Symbol,Integer,DoubleFloat,OutputForm),
ConvertibleTo SExpression) with
...
and see
...
interpret x ==
v := interpret(x)$Lisp
mkObj(unwrap(objVal(v)$Lisp)$Lisp, objMode(v)$Lisp)$Lisp

It only refers to the Lisp library, everything is hidden.
Further,
.. package ..
InputFormFunctions1(R:Type):with
packageCall : Symbol -> InputForm
++ packageCall(f) returns the input form corresponding to f$R.

has the definitions like
packageCall name ==
convert([convert("$elt"::Symbol), Rname,
convert name]$List(InputForm))@InputForm

I wonder, how can this help my example with Show.

I am stuck: do not see how to program this in Spad without defining
the copies for the constructors: INT1, Product1, List1 ...

I shall be grateful to anyone who demonstrates how to program in a resonable
way in Spad this example with the category Show and constructors
Integer, Product, List, Fraction, UP.

Thanks.

------
Sergei
mec...@botik.ru

Ralf Hemmecke

unread,
Apr 16, 2012, 3:03:49 AM4/16/12
to fricas...@googlegroups.com
> 1. I know what is "a domain of that category",
> but what does this mean: "a package of that category" ?

A category (or in other words, an interface) is (basically) just a list
of exports of the form

foo: A -> B

A domain or package is an implementation of this interface.
The difference between package and domain is: in the exports of a domain
appears % in the exports of a package it doesn't. But, I'm sure you know
this already. So where exactly is your problem with the above?

Ralf

Ralf Hemmecke

unread,
Apr 16, 2012, 3:19:44 AM4/16/12
to fricas...@googlegroups.com
Hi Sergei,

Concerning

>> 2. Here is a concrete and small contrived example/question presented by
>> an Haskell program.

of
http://groups.google.com/group/fricas-devel/browse_thread/thread/e2ed201491e8d2ab?hl=en
.

To be honest, I don't quite understand your problem.

Do you just want a way to print an object of a certain domain? In this
case implementing CoercibleTo(OutputForm) is the way to go. If you like
translate it into a category Show

Show: Category == CoercibleTo OutputForm

In your Haskell example you had to implement the function show for each
class. The same you must do for coerce: % -> OutputForm for each
respective domain.

I guess, you have already seen the following implementations.

https://github.com/hemmecke/fricas-svn/blob/master/src/algebra/product.spad.pamphlet#L57
https://github.com/hemmecke/fricas-svn/blob/master/src/algebra/fraction.spad.pamphlet#L66
https://github.com/hemmecke/fricas-svn/blob/master/src/algebra/list.spad.pamphlet#L99

That is in my eyes basically that what you want to achieve with your
Haskell example.

Did I misinterpret your question?

Ralf

Serge D. Mechveliani

unread,
Apr 16, 2012, 7:56:38 AM4/16/12
to fricas...@googlegroups.com
On Mon, Apr 16, 2012 at 09:19:44AM +0200, Ralf Hemmecke wrote:
> Hi Sergei,
>
> Concerning
>
>>> 2. Here is a concrete and small contrived example/question presented by
>>> an Haskell program.
>
> of
> http://groups.google.com/group/fricas-devel/browse_thread/thread/e2ed201491e8d2ab?hl=en
> .
>
> To be honest, I don't quite understand your problem.
>
> Do you just want a way to print an object of a certain domain? In this
> case implementing CoercibleTo(OutputForm) is the way to go.

1.
In the needed interface, Axiom
(my function parseEvaluateShow : String -> String in Spad)

must return a String to the pipe to DoCon (Haskell)
(DoCon knows ab initio the domain D of the result, and it converts this
string to D).
For example, Axiom returns "([4,3], [-2, 1])",
and DoCon knows that this is for Integer[x], and it converts this
string to the internal data (UPol "x" [(-2,4), (1,3)])
-- which represents -2*x^4 + x^3.
parseEvaluateShow is defined to return here "([4,3], [-2, 1])"
rather than "-2*x^4 + x^3", because the former is more close both to
the DoCon internal data and to the Spad internal data.

How precisely this `show' maps -- I have demonstrated in a small Haskell
code in a recent letter.

And Spad data --> String must be as fast as possible.
So, data :: OutputForm --> String
and data :: InputForm --unparse -> String

must be avoided here. Right?

So, I need to directly print the computed internal data to String
rather than to OutputForm.
Let it be CoercibleTo(String) -- if such has sense.
And I call `show' this `coerce'.

So, I need to define show : T -> String
(or maybe, coerce : T -> String)

recursively for the constructors of Integer, Product, List, Fraction, UP
(so far, restict to this small set).
For example,
coerce : List Product(Fraction Int, UP(x, Fraction Int)) -> String

must work, and it must work for any sensible compositon of these
constructions.


2. This is also an example on programming in Spad
-------------------------------------------------

How to program in Spad in a "categorial" style?
Take this `show : T -> String' as an user operation, and program its
instances by new for the above 5 constructors, without replacing `show'
with any existing library operations.
I can do this in Haskell, the demonstrated code is small.
So: I understand how to program in Haskell.
But I fail to program this in Spad (without defining copies for certain
5 library domain constructors).

So: I do not understand, generally, how to program in Spad.
That is the problem.

The first real problem was of a recursive tree domain.
It is done by rather a complex code -- but let it be.
Now, I face the second problem.
Probably, I am missing something about packages/domains.

> If you like translate it into a category Show
>
> Show: Category == CoercibleTo OutputForm
>
> In your Haskell example you had to implement the function show for each
> class.

I implemented the instances of `show' for each _domain constructor_ from
the set of {Integer, (,) [], Fraction, UPol}.


Sorry, I look into fraction.spad.pamphlet, list.spad.pamphlet, and
cannot find its relation to my question.
1) I have explained what `show' must do,
2) you observe the corresponding Haskell code above, it is small and
clear.
Can anybody demonstrate the correspoding Spad code for this problem?

Regards,

-----------------
Serge Mechveliani
mec...@botik.ru

Serge D. Mechveliani

unread,
Apr 16, 2012, 8:45:56 AM4/16/12
to fricas...@googlegroups.com
On Mon, Apr 16, 2012 at 09:03:49AM +0200, Ralf Hemmecke wrote:
>> 1. I know what is "a domain of that category",
>> but what does this mean: "a package of that category" ?
>
> A category (or in other words, an interface) is (basically) just a list
> of exports of the form
>
> foo: A -> B
>
> A domain or package is an implementation of this interface.
> The difference between package and domain is: in the exports of a domain
> appears % in the exports of a package it doesn't. But, I'm sure you know
> this already.

Spad understands d : D, for a domain D.
But if D is a package, it, probably would not.
Respectively, if d : D, D : Ring, then Spad understands what is d*d,
without the user program specifying the origin of "*".
And with a package, the user program needs also to define from where the
function f is taken which is applied to d.
Right?

So where exactly is your problem with the above?

The problem is: how to follow the advice?
1) Define
category Show : Category with show : % -> String

All right.

2) "And define packages of that category".

What packages to define in order to make `show' to print as folows?

show ( [(1,-1),(2,-2)] :: List Product(INT,INT) ) -->
"[(1,-1),(2,-2)]"

show ( [ [(1,-1),(2,-2)], [(3,4)] ] :: List List Product(INT,INT) )
-->
"[[(1,-1),(2,-2)],[(3,4)]]",
and so on, for compositions?

Regards,

------
Sergei
mec...@botik.ru


Ralf Hemmecke

unread,
Apr 16, 2012, 8:52:44 AM4/16/12
to fricas...@googlegroups.com
> So: I do not understand, generally, how to program in Spad.
> That is the problem.

Can you confirm that you have studied the Aldor User Guide completely?
That's in my view the best way to understand SPAD.

Ralf

Serge D. Mechveliani

unread,
Apr 16, 2012, 12:25:53 PM4/16/12
to fricas...@googlegroups.com

I never looked into it.

Now, suppose that I study it. All right, I have heard that Aldor allows
adding categories to the library domains (as any sensible language must).
So, I shall use Aldor and declare the category Show, and then add its
instances to the domains of Integer, Product, List, Fraction, UPol --
similar as I do in Haskell.
May be, it will work (is Aldor workable?).
But this approach is not compiled in Spad.
If it is in Aldor, then how do people use the aimed Haskell interface when
Aldor is not open source, and there are problems with the license?
What shall I do further with this Aldore code?

Again: Bill Page and Waldek wrote that my problem with
parse : String -> Product(T, String)
can be programed by defining certain particular packages.
Now, I replace `parse' with even simpler problem of show : T -> String.
And ask: how to program it for compositions only of the _3_ constructors:
Integer, Product, List. What precisely are these packages?
May be, 20 non-empty line code to demonstrate.
I demonstrate it in Haskell:

-------------------------------------------------------------------
class Show1 a where show1 :: a -> String
--

-- `Show1' is taken to avoid clash with `Show' of the standard library.

-- `::' <-> `:' of Spad, `=' <-> `==', `:=', ':' <-> cons.


-- `a', `b' ... <-> category or a package parameter in Spad.

-- Integer, (,), [] are constructors from the standard library,
-- (a, b) <-> Product(a, b), [a] <-> List a.

instance Show1 Integer where show1 = show

-- use the library operation for Integer

instance (Show1 a, Show1 b) => Show1 (a, b)

-- print from (Pair a b) via printing (show1) for `a' and `b'

where
show1 (x, y) = concat["(", show1 x, "," show1 y, ")"]

instance Show1 a => Show1 [a] -- implementation for List: print from
where -- (List a) via show1 for `a'.


show1 [] = "[]"
show1 (x : xs) = concat [ "[", show1 x, showL xs, "]" ]
where
showL [] = ""
showL (x: xs) = concat ["," show1 x, showL xs]

---------------------------------------------------------------------

-- 12 non-empty lines. Example of usage:

show1 ( [ [(1,2),(3,4)], [(5,6)] ] :: List (List (Pair Integer)) ) =

"[[(1,2),(3,4)],[(5,6)]]"

What is the corresponding code in Spad, what are these (1-3) packages?
Is this so difficult to demonstrate the corresponding may be, 20 line
code?

Regards,

------
Sergei
mec...@botik.ru


Waldek Hebisch

unread,
Apr 16, 2012, 12:49:26 PM4/16/12
to fricas...@googlegroups.com
Ralf Hemmecke wrote:
>
> > 1. I know what is "a domain of that category",
> > but what does this mean: "a package of that category" ?
>
> A category (or in other words, an interface) is (basically) just a list
> of exports of the form
>
> foo: A -> B
>
> A domain or package is an implementation of this interface.
> The difference between package and domain is: in the exports of a domain
> appears % in the exports of a package it doesn't.

Actually, internaly in FriCAS the only difference between
package and domain is that package uses ')abbrev package ...'
and domain uses ')abbrev domain ...'. In other words the
real difference is what useres think: intuitively type T is
a package if you are not going to create data of type T,
otherwise it is a domain. The definition above tries to
approximate this: usualy one does not includue useless
functions in domain/package so if '%' appears in signatures
then presumably one in going to create some date that type,
OTOH creation functions are typically included in domains,
so if no signatures contains '%' then it resonable to suspect
that nobady is going to create something of that type.
However, note that in principle one can create data outside
given type and then pretend to it. OTOH one sometimes
inherits useless signatures.

--
Waldek Hebisch
heb...@math.uni.wroc.pl

Ralf Hemmecke

unread,
Apr 16, 2012, 1:10:18 PM4/16/12
to fricas...@googlegroups.com
> OTOH creation functions are typically included in domains,
> so if no signatures contains '%' then it resonable to suspect
> that nobady is going to create something of that type.
> However, note that in principle one can create data outside
> given type and then pretend to it.

If you think in terms of using "pretend" for an ordinary SPAD program,
then you are not programming SPAD.

As said before, "pretend" should only be used if nothing else is
possible. Inhabiting packages with "elements" is certainly not a
reasonable way of using SPAD.

Ralf

Serge D. Mechveliani

unread,
Apr 16, 2012, 1:11:54 PM4/16/12
to fricas...@googlegroups.com


Earlier I demonstrated two pieces of Haskell code to formulate the
problem.
But may be, people do not want to look into the Haskell code.

ASo I re-formulate it in Spad --
only assuming that it allows adding category instances to the standard
library domain constructors.
So, the code is contrived:

------------------------------------------------------------------------
category Show() : Category == SetCategory with show : % -> String

--------------
domain Integer() : Export == Implementation where
-- add Show to the domain of Integer
Export == Join(Integer export, Show)

Implementation == Integer add
show n == string n

--------------
domain Product(S : SetCategory, T : SetCategory) :
Export == Implementation where
Export == Product(S,T) export
if S has Show and T has Show then Show
-- add Show to the domain of Product

Implementation == Product(S, T) add
if S has Show and T has Show then Show
-- add Show to the domain of Product

Implementation == Product(S, T) add

if S has Show and T has Show then
show(p : %) : String ==
concat[ "(", show (first p), ",", show (second p), ")" ]

--------------
domain List(T : Type) : Export == Implementation where

Export == Product export
if T has Show then Show -- add to the List(T) domain

Implementation == List(T) add

if T has Show then
show(xs : %) : String == -- print xs to string
empty? xs => "[]"
x := first xs
xs := rest xs
str := concat("[", show x)
while not empty?(xs) repeat
x := first xs
xs := rest xs
str := concat[str, ",", show x]
concat(str, "]")
------------------------------------------------------------------------

-- 29 non-empty lines.
Example of usage:
show ([ [construct(1,2), construct(3,4)],
[construct(5,6), construct(7,8)] ]
:: List List Product(Int, Int))
->
"[[(1,2),(3,4)],[(5,6),(7,8)]]"

Now, as Spad does not allow adding category instances to the standard
library domain constructors: how to improve this program for Spad ?
What precisely packages to write?
I do not understand what can be an alternative approach to the Spad-like
design displayed above.

Thanks,

------
Sergei
mec...@botik.ru

Ralf Hemmecke

unread,
Apr 16, 2012, 1:35:41 PM4/16/12
to fricas...@googlegroups.com
>> Can you confirm that you have studied the Aldor User Guide completely?
>> That's in my view the best way to understand SPAD.
>
> I never looked into it.
>
> Now, suppose that I study it. All right, I have heard that Aldor allows
> adding categories to the library domains (as any sensible language must).
> So, I shall use Aldor and declare the category Show, and then add its
> instances to the domains of Integer, Product, List, Fraction, UPol --
> similar as I do in Haskell.

I repeat: "That's in my view the best way to understand SPAD."
I never suggested that you use Aldor (unless it becomes free software).

With your Haskell code you are basically adding more functionality to
existing classes Integer, (), and []. The direct translation to Aldor
would be something like

-- class Show1 a where show1 :: a -> String
Show: Category == with
coerce: % -> String

--instance Show1 Integer where show1 = show
-- -- use the library operation for Integer

extend Integer: with Show == add
show(x: %): String == ... ((implementation))

Unfortunately, this does *not work* in SPAD, since SPAD is currently
still lacking the "extend" keyword.

The only option that I see (Waldek, please correct me if I am wrong) is
that you

A) go to the sources of Integer, Product, and List in the fricas source
tree add the export and the implementation of your show there and then
do everything to recompile FriCAS from scratch.

B) copy the 3 relevant source files I pointed to in my last mail to your
local directory. Add the exports and the implementation of the show
function there. Then run

build/scripts/document --tangle="domain INT Integer" --output int.spad

(you find this document script in your build directory of a previous
compilation of fricas)

Do similar things for Product, Fraction, and Lisp, etc.

Then in a running fricas session, you say

)compile int.spad

That will replace the existing Integer domain with your local one (which
by construction has the same source code + your show).

I never did (B), but I think, it should work this way.

Ralf

Ralf Hemmecke

unread,
Apr 16, 2012, 1:42:14 PM4/16/12
to fricas...@googlegroups.com
Sorry, I read your mail too late. The code you demonstrate here should
also work. What is so bad with it except tht it is a bit lengthy?

You cannot expect that code that looks elegant in one language looks
equally elegant in another one. There are probably also SPAD programs
that you cannot equally elegantly express in Haskell.

We are not starting a language war here, are we? (I don't take part in
it anyway.)

Ralf

Waldek Hebisch

unread,
Apr 16, 2012, 2:16:42 PM4/16/12
to fricas...@googlegroups.com
Serge D. Mechveliani wrote:
>
> I am sorry, may I ask, again, a question about categories and standard
> constructors?
> This time it is more concrete.
> Concerning my request on adding categories to standard constructors
> Waldek wrote
>
> > Why do you need Integer (etc.) to have ParseCategory? You can have:
> >
> > ParseCategory(T : SetCategory) : Category == SetCategory with
> > parseElem : String -> Product(T, String)
> > [..]
> >
> > and then implement packages of that category.
>
> 2. Here is a concrete and small contrived example/question presented by
> an Haskell program.
>

OK, so you really do not care about adding category to Integer,
what you really want is to define a function, recursively
combining pieces defined for various types. In other
words we have your old problem of dispatching on types.

Now, adding your function to Integer, ..., etc. solves dispactching
problem by using normal Spad dispatching. Still, for me it does
not look like "right" solution: currently Integer has 107
operations. If each user could at will add operations to Integer
we may easily get hundreds or thousends of operations in
Integer with risk of name clashes etc.

Now, I admit that if you insist on your interface, that is
all you have is just a type (which is build from limited
set of constructors but allows arbitrary composition), then
Spad does not offer solution to you problem (as opposed
to workarounds).

OTOH, when we look at your real problem (that is of creating
Haskell interface), than I feel that there is quite
satisfactory solution. Namely, you start from a string
describing type. Parsing this string you create type
and a package containg appropriate function(s): a
function to parse strings to the type and a function to
unparse elements of the type to stings. Concretely, you have:

UnparserCategory(T : Type) : Category == with (show : T -> Sting)

SparseUnivariatePolynomialUnparser(R : Ring, UR : UnparserCategory(R)) : _
UnparserCategory(SparseUnivariatePolynomial(R))
== add
show(x) ==
x = 0 => "([], [])"
dl := List(NonNegativeInteger) := reverse(map(degree, monomials(p)))
cl := List(String) := reverse(map(show$UR, coefficients(p)))
s1 : String := toString(first(dl))
s2 := frist(cl)
for i in rest(dl) for c in cl repeat
s1 := concat(toString(i), concat(", "), s1)
s2 := concat(c, concat(", "), s2)
concat(["([", s1, "], [", s2, "])"])

Note: I assumed that there is a function to convert integers to
strings. ATM one has to do something like

toString(i : Integer) : String == FORMAT(nil, "~d", i)$Lisp

or

toString(i : Integer) : String == unparse(i::InputForm)$InputForm


Case of Product is easier:

ProductUnparser(A : SetCategory, B : SetCategory,
UA : UnparserCategory(A), UB : UnparserCategory(B)) _
: UnparserCategory(Product(A, B))
== add

show(x) ==
concat("[", concat(show(first(x))$UA, concat(", ", _
concat(show(second(x)$UB, "]")))))


Alternatively, you can have 'make_show' function and pass
unparsers of parameters of type as parameters to 'make_show'.
If you need a single function (or a few loosely connected
functions), then I would probably use 'make_show' version.
If there are more related functions than passing package
as type parameter looks more attractive than passing several
functions.

Note: In principle one could pass a package as parameter to
'make_show'. However calling functions from such package
is less efficient than other function calls, so the two
alternatives I gave are faster.

--
Waldek Hebisch
heb...@math.uni.wroc.pl

Serge D. Mechveliani

unread,
Apr 16, 2012, 2:39:40 PM4/16/12
to fricas...@googlegroups.com
On Mon, Apr 16, 2012 at 07:42:14PM +0200, Ralf Hemmecke wrote:
> Sorry, I read your mail too late. The code you demonstrate here should
> also work. What is so bad with it except tht it is a bit lengthy?

Bad is _only_ that it must not work!

Its length does not matter, and I do not consider it as large.
I wrote about length only to show that my Spad-like example is small and
clear, so that people can read and consider it.

> You cannot expect that code that looks elegant in one language looks
> equally elegant in another one.

Again: this Spad-like code is small and elegant all right.

The matter is that it _must not work_!

Waldek and other people wrote that (if only I understand them correctly)

an user Spad program cannot add new category instances
to any Axiom library domain.

For example, one cannot increase Integer with an instance of my Show
category. And in my code below Integer is re-defined, extended.
Similarly, the set of instances related for Product(S,T) and List(T)
are re-defined, extended.

Hence the below code must not work in Spad. Must it?

People, please, consider the below code and tell: what is wrong in it
(besides absence of the )abbrev line) ?
(I never tried to compile it, because was sure that it would not).

If it does not work in Spad, then what is the appropriate replacement?

Regards,

------
Sergei
mec...@botik.ru

If Spad accepted this, then the Example of usage may be:

show ([ [construct(1,2), construct(3,4)],
[construct(5,6), construct(7,8)] ]

:: List List Product(INT, INT))
->
"[[(1,2),(3,4)],[(5,6),(7,8)]]"

Serge D. Mechveliani

unread,
Apr 16, 2012, 3:13:48 PM4/16/12
to fricas...@googlegroups.com
On Mon, Apr 16, 2012 at 08:16:42PM +0200, Waldek Hebisch wrote:
> Serge D. Mechveliani wrote:
> >
> > I am sorry, may I ask, again, a question about categories and standard
> > constructors?
> > This time it is more concrete.
> > Concerning my request on adding categories to standard constructors
> > Waldek wrote
> >
> > > Why do you need Integer (etc.) to have ParseCategory? You can have:
> > >
> > > ParseCategory(T : SetCategory) : Category == SetCategory with
> > > parseElem : String -> Product(T, String)
> > > [..]
> > >
> > > and then implement packages of that category.
> >
> > 2. Here is a concrete and small contrived example/question presented by
> > an Haskell program.
> >
>
> [..]

> Now, I admit that if you insist on your interface, that is
> all you have is just a type (which is build from limited
> set of constructors but allows arbitrary composition), then
> Spad does not offer solution to you problem (as opposed
> to workarounds).

Let it be all compositions of Integer, Product, List.
If `show' works for this, then I can program all the rest.

If you also similarly define `show' for List, will this work for

show ([ [construct(1,2), construct(3,4)],
[construct(5,6), construct(7,8)] ]

:: List List Product(Int, Int))
?
Thanks,

------
Sergei
mec...@botik.ru



Serge D. Mechveliani

unread,
Apr 16, 2012, 3:26:03 PM4/16/12
to fricas...@googlegroups.com
On Mon, Apr 16, 2012 at 08:16:42PM +0200, Waldek Hebisch wrote:

> [..]

>
> Now, adding your function to Integer, ..., etc. solves dispactching
> problem by using normal Spad dispatching. Still, for me it does
> not look like "right" solution: currently Integer has 107
> operations. If each user could at will add operations to Integer
> we may easily get hundreds or thousends of operations in
> Integer with risk of name clashes etc.
>

Each user will use Standard Axiom functionality in Integer (I)
+ User functionality (II).

(I) is constant. (II) is added by the user, it depends on the user.

And in theory, there are infinitely many categories to which Integer
belongs to.
The Axiom library chooses a fixed finite set of such categories.
And each user chooses one's own additional finite set of such categories.
Simialr is with other standard constructors.
`extend' is quite necessary.

Regards,

------
Sergei
mec...@botik.ru

Ralf Hemmecke

unread,
Apr 16, 2012, 4:40:52 PM4/16/12
to fricas...@googlegroups.com
> Note: I assumed that there is a function to convert integers to
> strings. ATM one has to do something like
>
> toString(i : Integer) : String == FORMAT(nil, "~d", i)$Lisp
>
> or
>
> toString(i : Integer) : String == unparse(i::InputForm)$InputForm

Looking into the implementation of the function "latex" also suggests

toString(i: Integer): String == string(i)$String

> Case of Product is easier:
>
> ProductUnparser(A : SetCategory, B : SetCategory,
> UA : UnparserCategory(A), UB : UnparserCategory(B)) _
> : UnparserCategory(Product(A, B))
> == add
>
> show(x) ==
> concat("[", concat(show(first(x))$UA, concat(", ", _
> concat(show(second(x)$UB, "]")))))

Oh, yes, Waldek, you are right. That should currently be the way to go.
Though, I somehow agree with Sergei, that extend *is* something reasonable.

The argument that there will be name clashes is no problem in my eyes,
because (1) extend can be used locally and so the user can take care of
clashes, and (2) if user code eventually enters the "official"
repository, name clashes can be dealt with before the code goes in.

I am sure you agree that doing this "workaround" is more cumbersome than
a simple "extend".

Ralf

Mark Clements

unread,
Apr 16, 2012, 5:10:40 PM4/16/12
to fricas...@googlegroups.com
A hack using packages is given below. This currently works for T in {Integer, Symbol}, List(T), Product(S,T) and Product(List(S),List(T)). Extension should not be too painful...

Kindly, Mark.

-- base types
)abbrev package SHOW Show
Show() : Export == Implementation where
Export == with
show: Integer -> String
show: Symbol -> String
-- etc
Implementation == add
show (n:Integer) == string n
show (n:Symbol) == string n
-- etc

-- single type (e.g. homogeneous aggregates)
)abbrev package SHOW1 Show1
Show1(T:SetCategory) : Export == Implementation where
Export == with
if Show has (show:T->String) then
show: List(T) -> String
Implementation == add
if Show has (show:T->String) then
show(xs : List(T)) : String == -- print xs to string


empty? xs => "[]"
x := first xs
xs := rest xs
str := concat("[", show x)
while not empty?(xs) repeat
x := first xs
xs := rest xs
str := concat[str, ",", show x]
concat(str, "]")

-- two types
)abbrev package SHOW2 Show2
Show2(S:SetCategory, T:SetCategory) : Export == Implementation where
Export == with
if Show has (show:S->String) and Show has (show:T->String) then
show: Product(S,T) -> String
Implementation == add
if Show has (show:S->String) and Show has (show:T->String) then
show(p : Product(S,T)) : String ==
concat[ "(", show (selectfirst p), ",", show (selectsecond p), ")" ]

-- composition
)abbrev package SHOWN Shown
Shown(S:SetCategory, T:SetCategory) : Export == Implementation where
Export == with
if Show1(S) has (show:List(S)->String) and Show1(T) has (show:List(T)->String) then
show: Product(List(S),List(T)) -> String
-- etc
Implementation == add
if Show1(S) has (show:List(S)->String) and Show1(T) has (show:List(T)->String) then
show(p : Product(List(S),List(T))) : String ==
concat[ "(", show (selectfirst p), ",", show (selectsecond p), ")" ]

)if false
show 'a
show [1,2,3]
show makeprod(1,'a)$Product(Integer,Symbol)
show makeprod([1,2],[a,b])$Product(List(Integer),List(Symbol))
)end if

Serge D. Mechveliani

unread,
Apr 17, 2012, 5:27:14 AM4/17/12
to fricas...@googlegroups.com
On Mon, Apr 16, 2012 at 09:10:40PM +0000, Mark Clements wrote:
> A hack using packages is given below. This currently works for T in {Integer, Symbol}, List(T), Product(S,T) and Product(List(S),List(T)). Extension should not be too painful...
>
> Kindly, Mark.
>

1. But how to call _this_ `show', for example, for
List List List Integer ?
So far, I failed with List List Integer.
Am I missing something?

2.
> if Show has (show:T->String) ...

Did you mean `if T has (show:T->String) ...' ?

Regards,

------
Sergei
mec...@botik.ru


-------------------------------------------------------------------------

> --
> You received this message because you are subscribed to the Google Groups "FriCAS - computer algebra system" group.
> To post to this group, send email to fricas...@googlegroups.com.
> To unsubscribe from this group, send email to fricas-devel...@googlegroups.com.
> For more options, visit this group at http://groups.google.com/group/fricas-devel?hl=en.
>
>

Serge D. Mechveliani

unread,
Apr 17, 2012, 6:19:05 AM4/17/12
to fricas...@googlegroups.com
On Mon, Apr 16, 2012 at 08:16:42PM +0200, Waldek Hebisch wrote:
> Serge D. Mechveliani wrote:
[..]
> > Concerning my request on adding categories to standard constructors
> > Waldek wrote
> >
> > > Why do you need Integer (etc.) to have ParseCategory? You can have:
> > >
> > > ParseCategory(T : SetCategory) : Category == SetCategory with
> > > parseElem : String -> Product(T, String)
> > > [..]
> > >
> > > and then implement packages of that category.
> >
> > 2. Here is a concrete and small contrived example/question presented by
> > an Haskell program.
[..]


I am trying to understand and to simplyfy the example:

------------------------------------------------------------------------
)abbrev category UNPARSE UnparserCategory
UnparserCategory(T : Type) : Category == with (show : T -> String)

)abbrev package LUNPARS ListUnparser
ListUnparser(T : Type, UT : UnparserCategory(T)) : _
UnparserCategory(List(T))
== add
show(xs : List T) : String ==

empty? xs => "[]"
x := first xs
xs := rest xs

str := concat("[", show(x) $UT)


while not empty?(xs) repeat
x := first xs
xs := rest xs

str := concat[str, ",", show(x) $UT]
concat(str, "]")
------------------------------------------------------------------------

I defined ListUnparser after your sample of
SparseUnivariatePolynomialUnparser,
without much understanding, and in order to see how this `show' works
for all compositions of Integer and List:
List INT, List List INT, etc.

1. Is this ListUnparser what you meant?

2. Must it be `)abbrev package' or `)abbrev domain' ?

3. If it is what you meant, then how to call `show' for
List INT, List List List INT ?

I am asking this naive questions because hope that your answers will
help me to understand your approach.

Thanks,

------
Sergei
mec...@botik.ru

Waldek Hebisch

unread,
Apr 17, 2012, 11:55:36 AM4/17/12
to fricas...@googlegroups.com

^^^^ Indentation error
str


> ------------------------------------------------------------------------
>
> I defined ListUnparser after your sample of
> SparseUnivariatePolynomialUnparser,
> without much understanding, and in order to see how this `show' works
> for all compositions of Integer and List:
> List INT, List List INT, etc.
>
> 1. Is this ListUnparser what you meant?

Yes.

> 2. Must it be `)abbrev package' or `)abbrev domain' ?

I would write 'package' but for compiler it does not matter.

> 3. If it is what you meant, then how to call `show' for
> List INT, List List List INT ?
>
> I am asking this naive questions because hope that your answers will
> help me to understand your approach.

(3) -> l := [[-1, 2], []]

(3) [[- 1,2],[]]
Type: List(List(Integer))
(4) -> show(l)$ListUnparser(List INT, ListUnparser(INT, IntegerUnparser))

(4) "[[-1,2,[]"
Type: String

Of course, I defined appropriate IntegerUnparser. And missing final
"]" is because you forgot final assignment in the loop.

Note: you need to use 'show(l)$P' where P is appropriate package.
I suggest to build P when you analyze type descriptor (without
type descriptor building T would be tricky).


--
Waldek Hebisch
heb...@math.uni.wroc.pl

Waldek Hebisch

unread,
Apr 17, 2012, 12:04:10 PM4/17/12
to fricas...@googlegroups.com
Mark Clements wrote:
>
> A hack using packages is given below. This currently works for T in {Integer, Symbol}, List(T), Product(S,T) and Product(List(S),List(T)). Extension should not be too painful...
>
> Kindly, Mark.
>
> -- base types
> )abbrev package SHOW Show
> Show() : Export == Implementation where
> Export == with
> show: Integer -> String
> show: Symbol -> String
> -- etc
> Implementation == add
> show (n:Integer) == string n
> show (n:Symbol) == string n
> -- etc
>
> -- single type (e.g. homogeneous aggregates)
> )abbrev package SHOW1 Show1
> Show1(T:SetCategory) : Export == Implementation where
> Export == with
> if Show has (show:T->String) then
> show: List(T) -> String

This means that Show1 will only work for types mentioned in
Show. Conseqently your approach will be only able to handle
finite number of types -- for practical purposes this may be
enough, but Sergei wants infinite family...

--
Waldek Hebisch
heb...@math.uni.wroc.pl

Serge D. Mechveliani

unread,
Apr 17, 2012, 3:14:45 PM4/17/12
to fricas...@googlegroups.com
On Tue, Apr 17, 2012 at 05:55:36PM +0200, Waldek Hebisch wrote:
[..]
> > I am trying to understand and to simplyfy the example:
> >
> > ------------------------------------------------------------------------
> > )abbrev category UNPARSE UnparserCategory
> > UnparserCategory(T : Type) : Category == with (show : T -> String)
> >
[..]

> (3) -> l := [[-1, 2], []]
>
> (3) [[- 1,2],[]]
> Type: List(List(Integer))
> (4) -> show(l)$ListUnparser(List INT, ListUnparser(INT, IntegerUnparser))
>
> (4) "[[-1,2,[]"
> Type: String
>
> Of course, I defined appropriate IntegerUnparser. And missing final
> "]" is because you forgot final assignment in the loop.
>

I cannot repeat your example.
And you do not show your IntegerUnparser.
I repeat below the improved code.
Please, what is wrong there?

Thanks,

------
Sergei
mec...@botik.ru


------------------------------------------------------------------------
INT ==> Integer

)abbrev category UNPARSE UnparserCategory
UnparserCategory(T : Type) : Category == with (show : T -> String)

)abbrev package INTUNPA IntegerUnparser
IntegerUnparser() : UnparserCategory(INT) == add
show(n : INT) : String == convert(n) :: String

)abbrev package LUNPARS ListUnparser
ListUnparser(T : Type, UT : UnparserCategory T) :
UnparserCategory(List T)


== add
show(xs : List T) : String ==
empty? xs => "[]"
x := first xs
xs := rest xs
str := concat("[", show(x) $UT)
while not empty?(xs) repeat
x := first xs
xs := rest xs
str := concat[str, ",", show(x) $UT]
concat(str, "]")

------------------------------------------------------------------------

-> show(2)$IntegerUnparser
"2"

-> show([2,2])$ListUnparser(INT,IntegerUnparser)
"NIL"

This is FriCAS-1.1.6 + SBCL 1.0.55.

Serge D. Mechveliani

unread,
Apr 17, 2012, 3:34:24 PM4/17/12
to fricas...@googlegroups.com
On Tue, Apr 17, 2012 at 11:14:45PM +0400, Serge D. Mechveliani wrote:

> I cannot repeat your example.

> [..]

I am sorry, I fix indentation in the last line, so that it becomes
...


> while not empty?(xs) repeat
> x := first xs
> xs := rest xs
> str := concat[str, ",", show(x) $UT]
> concat(str, "]")

And now it works.
Now, I shall think about this design.
At least, you, probably, agree with that it is rather cumbersome:
to build this full package description ...

Thanks,

------
Sergei
mec...@botik.ru

Serge D. Mechveliani

unread,
Apr 18, 2012, 3:54:32 AM4/18/12
to fricas...@googlegroups.com
On Tue, Apr 17, 2012 at 05:55:36PM +0200, Waldek Hebisch wrote:
[..]
> >
> > ------------------------------------------------------------------------
> > )abbrev category UNPARSE UnparserCategory
> > UnparserCategory(T : Type) : Category == with (show : T -> String)
> >
> > )abbrev package LUNPARS ListUnparser
> > ListUnparser(T : Type, UT : UnparserCategory(T)) : _
> > UnparserCategory(List(T))
> > == add
> > show(xs : List T) : String ==
> > empty? xs => "[]"
> > x := first xs
> > xs := rest xs
> > str := concat("[", show(x) $UT)
> > while not empty?(xs) repeat
> > x := first xs
> > xs := rest xs
> > str := concat[str, ",", show(x) $UT]
> > concat(str, "]")
>
> ^^^^ Indentation error
> str
> > ------------------------------------------------------------------------
> >
[..]

> (3) -> l := [[-1, 2], []]
>
> (3) [[- 1,2],[]]
> Type: List(List(Integer))
> (4) -> show(l)$ListUnparser(List INT, ListUnparser(INT, IntegerUnparser))
>
> (4) "[[-1,2,[]"
> Type: String
>
> Of course, I defined appropriate IntegerUnparser. And missing final
> "]" is because you forgot final assignment in the loop.
>
> Note: you need to use 'show(l)$P' where P is appropriate package.
> I suggest to build P when you analyze type descriptor (without
> type descriptor building T would be tricky).
>

To program forming this package P looks the same as the initial problem
of programming `show'.
(?)
In principle, I need to try and see now whether the categories Show and
Parse, and the related packages made after your design, can help my
parser
parseEvaluateShow : String -> String
written in Spad.
May be, this will work, I am not sure, so far.
But I hope to convince the Spad developers to introduce `extend' -- which
will make possible a most natural general style "by domain construction'.

Regards,

------
Sergei
mec...@botik.ru

Reply all
Reply to author
Forward
0 new messages