On 14/08/2012, at 8:46 AM, Dobes Vandermeer wrote:

> 
> You know, I was just wondering if the "**" and ",," syntax isn't a but too 
> fancy - and probably confusing.  I think operators should be used in the way 
> people are familiar with, and rather than inventing new obscure operators it 
> makes more sense to use a named function/operator instead.
> 
> Why not use functions instead, like:
> 
> class Tuple {
>   typedef fun headtype(X) => ... magic ...;
>   typedef fun tailtype(X) => ... magic ...;
>   typedef fun headtailtype(X) => headtype(X)*tailtype(X);
> 
>   fun head[T](x:T):headtype(T) => ... magic ...
>   fun tail[T](x:T):tailtype(t) => ... magic ...
>   fun headtail[T](x:T) => head(x), tail(x);
> }

Because at present (on todo list!) you cannot use functions in a pattern match.
[C# and Scala allow this, Ocaml and Haskell do not ..]

However: The symbols , and ,, are not functions, they're constructors.

To understand this consider:

        * : TYPE * TYPE -> TYPE

This takes two types and returns a single type. The theoretical name for

        F: TYPE -> TYPE

is "functor", its a structure preserving map between categories. The names used
for 

        G: TYPE * TYPE -> TYPE

is bi-functor. Its a structure preserving map from a pair of categories.

This is a "tuple" at the meta-level, not at the type level. Similarly:

When I write:

        a , b

the "," there is NOT a function, its a constructor. It has two arguments.  It's 
the only "thing"
allowed to have two arguments (functions are only allowed to have one argument).

A function is:

        f: TYPE -> TYPE

It takes one argument, perhaps a tuple. This decomposition is fundamental.
Its how we can write a function with two arguments .. and still give it one
argument:

        fun f(x;int, y:long) => x.long + y;
        var a = 1; var b = 2L; var c = a,b;
        println$ f (a,b), f c;

The important thing here is that

        f: TYPE -> TYPE

is not just a function whose type is in the category TYPE,
Its also a VALUE. Whereas operator "," is not.

> Also I think it would make sense to support iteration as well.  This doesn't 
> appear at this distance like it is less safe or less difficult to implement:
> 
> for x in 3.14,'foo',1234 do
>   // compiler unrolls this 3 times ...
> done

Excellent idea. Type safe macros for table generation over heterogenous types!

> Also of interest is that tuple fields can now be operated on by index, 
> whether using recursion or iteration.

This still requires a bit more work. The category theory usually says:

        proj0 : A * B -> A
        proj1: A * B -> B

These are the projection functions. We can make a tuple:

        proj0, proj1

but this is still a tuple, not an array, so it cannot be indexed. But if we use 
these:

        array_proj0 : A* B -> A + B
        array_proj1 : A * B -> A + B

instead, they're the same type, and

        array_proj0, array_proj1

is now an indexable array. in particular:

        array_proj : 2 -> A * B -> A + B

i.e. we can use an index to select the projection. If A = B then we can also 
use smash:

        smash: X + X -> X

to "get rid" of the sum so we don't have to do a match on all the cases.
you cannot use "smash" on a tuple of course. 

My problem is that "tuple of all the same type is an array" is wrong.
If all the elements are of the same type, "smash" is being applied
automagically by Felix and it shouldn't be.

I need to fix the type system so the core indexing works THE SAME for
tuples and arrays, and then for arrays we apply smash to get back our
ordinary array indexing. That means that indexing a tuple and array
will both work and both return a sum but for an array you can smash
the result to get rid of the variant so you don't have to pattern match
an array of 1000 elements with 1000 cases.

The biggest problem is something you noted earlier .. a lack of symbols.
This also translates into the type system Ocaml representation:
every implemented "operator" has to have an operation in the compiler
and all the semantics. I'm actually trying to get rid of them, for example

        BEXPR_get_n of n * e

is used to access the n'th component of a tuple e. Previously n had to
be a unitsum, in particular, n in the Ocaml rep was just an integer constant.

But this is just a projection, which is a function .. so I am ALSO using

        BEXPR_apply of e * e

i.e. application, and if the first "e" is an int instead of a function, I use
a trick to pretend it means projection.

> 
> Once I have this IDE thing tamed (soon, hopefully) I might take a closer look 
> at this dynamic polymorphism when operating on hetergenous collections.  It 
> should be as transparent as possible for someone to have a list of objects of 
> varying types and operate on the elements without a lot of boxing/unboxing.

Yes indeed. because normally people in weak languages like C++ use
RTTI to do that boxing and unboxing, and that means BAD DESIGN and
RUN TIME ERRORS.

We cannot always get rid of run time errors: a type system strong
enough to do that would probably require such complex annotations
that it would be more work writing the types than the part of the
code that does the work. There's a tradeoff between expressive power
and notational complexity.

But modern theory (including theorem provers) are now allowing
much more expressive type systems with little inconvenience.

In fact type theorists usually harp on about a system supporting
"type inference" which means " you do not need to write any type
annotations AT ALL". A system which has that property AND
is very expressive is considered desirable.

[Felix type system does NOT have that property because I choose
to support overloading instead: some kind of inference and overloading
can co-exist but it is too hard for me]

> In games this sort of thing is rather common,

Yes, in games bugs are common. It costs huge amounts of money
to test games because programmers continue to insist on using
some of the worst possible programming technology to implement
them.  Indeed it has become a cultural aspect of gaming, that you use
crappy technology like C or user accessible interpreters like Lua
which are as almost bad as you can get in terms of safety.

Doing this requires extensive testing. It makes money for the big
game houses: cheap labour (anyone can write C) and expensive
testing exclude smaller companies. Big companies just throw
money at the problem (hire more cheap programmers).
Small companies can't do that. They HAVE to use better
technology and expensive programmers or they can't compete ..
and at the moment that better technology -- type safe AND fast --
does not exist.

Felix is intended to fill the gap. Fast and safe. Maybe requires
someone that knows some computer science to use it.

> I think people who are accustomed to OO programming or lua programming would 
> find it rather perplexing that this is so difficult to do in Felix.  At 
> least, I find it puzzling!

It's not difficult. Its WRONG. Its only difficult to do it right.
That means: static type checking.

Just consider a simpler example. In Felix you have darray which is equivalent
to vector<> in C++.

If you try to zip two vectors, you can get a run time error if the lengths
don't agree.

You may think this is normal and the only way to do it but you're WRONG.

Even C++ can get this right with templates: arrays in C++ has *statically* 
determined
known at compile time lengths (provided you don't let them degrade into 
pointers).

However the typing to track that two arrays have the same length is
non-trivial. Making it possible to write code where you can write
ONE function that can zip any two arrays of the same length together
and will give a compile time error if they're not the same length
is HARD. Its a whole research area (dependent typing).

So programmers just use dynamics because type systems aren't
expressive enough. However its wrong. Barry Jay showed how to 
write array polyadic code, which is one level of difficulty harder than
tracking mere array lengths -- it "genericises" the rank as well,
and all with static type checking. Felix is trying to do some of  this

It isn't working well yet -- I interrupted development for two other
improvements: recursive instantiation (polymorphic recursion)
and recursive decomposition of tuples (which uses polymorphic
recursion).


--
john skaller
skal...@users.sourceforge.net
http://felix-lang.org




------------------------------------------------------------------------------
Live Security Virtual Conference
Exclusive live event will cover all the ways today's security and 
threat landscape has changed and how IT managers can respond. Discussions 
will include endpoint security, mobile security and the latest in malware 
threats. http://www.accelacomm.com/jaw/sfrnl04242012/114/50122263/
_______________________________________________
Felix-language mailing list
Felix-language@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/felix-language

Reply via email to