guile-user
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Typed Guile?


From: Panicz Maciej Godek
Subject: Re: Typed Guile?
Date: Thu, 8 Nov 2012 18:03:51 +0100

> The first part of this message may look irrelevent, but you'll
> understand why I decided to start this way.
>
> I'm going to write a library.
>
> Here is the list of things I care about (from the most important to
> the least important):
>
>  - Strict type system;
>  - Wide community;
>  - Performance.
>
> There are several candidates:
>
>  - Haskell;
>  - Typed Racket;
>  - Typed Clojure*.
>
> Which one should I choose?
>
> (Please don't answer right now.)

Oh, come on, it's been months!

> I've already tried to ask TR people:
>
> "Typed Racket is designed for Racket. One day Guile will have a Typed
> Guile companion, and Chez Scheme may have a Typed Chez companion but
> until then TR is for Racket." [1]
>
> Is it this bad? Do we really need Typed Guile?
>
> Can we somehow adapt the static code to achieve its features in Guile?
>
> I'm really concerned about code reuse. It's time to stop reinventing
> the wheel.
>
> My writing skills are not very great...
> So I'm going to summarize the above:
>
>  1. What language should I choose for my library?
>  2. Do we need Typed Guile?

I'm glad that you wrote. I'm really dying for a good type system for
guile. Obviously, type system can, in the long run, have some positive
impact on performance, as it allows to avoid run-time type checking.
But this isn't my concern for now.
For me, the biggest (and most urgent) issue is the expressive power of
the language, and second biggest, error-proneness.

I've heard a lot about the type system of Haskell, but I don't know
any details. Neither do I know much about racket's, but I know for
sure that it doesn't suit my taste.

There is, however, a good base for a type system shipped with guile's
GOOPS. And I think that it would be wisest to extend it, so the
language remains coherent.

GOOPS' type system is lacking two features, the first one being the
return value of a procedure, and the second, types for collections.

So I think, that type annotation for the return value of a method
could be a coherent extension to the existing system. For example, one
could write:
(define-method (name (arg1 <type1>) ... (argN <typeN>)) : <return-type>
  body ...)
slightly extending the define-method as it is used today.

The second postulate is more difficult to agree upon with. I think the
nicest way would be to use the omnipresent pattern language, so for
instance the procedure taking the list of numbers could be written as:
(define-method (mean (S (<number> ...))) : <number>
  (/ (apply + S) (length S)))

(define-method (mean (v #(<real> ...))) : <number>
  (mean (vector->list v)))

It could be similarly used to define methods with variable number of
arguments of the same type, e.g.
(define-method (mean (n <number>) . (rest (<number> ...))) : <number>
  (mean (cons n rest)))

Unfortunately, the pattern language alone would be insufficient, at
least not in its present shape. That's because we would also like to
be able to specify the types of hashes and procedures, like below
(it's actually inspired by the code that I'm writing at the moment):
(define-method
  (handle-clients
    (connection (<number> . <number>))
    (clients (hash (<number> . <number>) (hash <symbol> <procedure>)))
    (handle-new-connection ((procedure <number>) : (hash <symbol>
<procedure>))))
  [body])

I don't know to what extent is this readable. My intention is that the
syntax (hash <key-type> <value-type>) would express a hash table such
that all its keys are of type <key-type>, and values of <value-type>,
respectively.
Similarly, ((procedure <arg1-type> ... <argN-type>) : <return-type>)
stands for the procedure of a certain type.
This notation is just a proposition for what I'm willing to express.
There is a question regarding the implementation, however (especially,
defining new types). I think it would be a problem for the
pattern-matcher to distinguish between (hash <key-type> <value-type>)
[a hash] and (<hash> <key-type> <value-type>) [a list], so maybe
another notation would be required (like (% hash ...), (% procedure
...), or #%hash(<k> <v>) ..., or something similar).

I think that parsimony is one of the advantages of such a type system.
One could say that having any type system is better than having none,
but I don't think that this refers to the realm of Scheme :)
Secondly, building it atop of GOOPS would be valuable in this respect,
that it could be later adapted by the chicken's scheme COOPS object
system, which also derived from CLOS and seems compatible with GOOPS
(vide http://wiki.call-cc.org/eggref/4/coops).

I don't know what the rest of the community has to say about this, but
if you managed to implement this, I can promise that you'd have at
least one user :)

(Among the things that I dislike in the typed Racket is that firstly
it posits plurality without necessity, introducing labels like Listof,
that a programmer needs to memoize or look up in the documentation,
and secondly, it introduces not-much-telling identifier :, which,
although looks joyfully when used ("(:"), is quite far from the spirit
of SICP)

BTW Does anyone here know what does the #& ("box") quasi-pattern in
the Shinn-Wright pattern matcher stand for?

Best regards :)
M.



reply via email to

[Prev in Thread] Current Thread [Next in Thread]