On 15/08/2012, at 3:01 PM, Dobes Vandermeer wrote:

> I think what you are trying to say is that "headtail" shouldn't work on 
> something that isn't a tuple.  That makes sense.  

I'm saying a bit more than that it shouldn't: I'm saying the type system cannot 
let you apply
it to something that isn't a tuple, otherwise the type system isn't sound.

The trick is that when you apply it to a type variable, you don't know it its
a tuple or not, so you can either reject the program with a type error,
or you can wait until you know the concrete type.

For the generic tuple stuff to be useful at all, we don't want the first
solution because you'd have to write out your code to handle
all the cases (which is what we're trying to avoid). So we have to
do the second solution.

At the point we know, we have to apply an extractor function.
(Destructor, eliminator). Such as "head" and "tail".

But the best way to do this is with a pattern match.

The *ideal* situation would be "user defined pattern matches".
So we could just define

        head ..
        tail

and then provide a pattern matching syntax that uses them.

This can be done (I mean, the compiler can be modified to support it,
it can't be done right now). That would be cool (but I can't do everything
at once!)

> Also I see that there's no way for the overloading system to select a 
> function based on whether it takes a tuple because there's no type syntax for 
> that other than the ** thing you are working on now.

Precisely the right idea. Type classes DO provide overloading, but not
the Felix or C++ style of "open" overloading (where you can add overloads
willy-nilly). Instead they use a trick: the initial binding pretends the 
function
is polymorphic, then you get an error later if that assumption proves incorrect
(after the type variables are eliminated).

> So, the solution here wasn't as simple as I'd hoped.  HOWEVER my objection to 
> using ",," stands!  Is there no better way?

Of course: 

        lib/std/grammar/patterns.flxh


  sas_pattern := stuple_cons_pattern "as" sname =># "`(pat_as ,_sr ,_1 ,_3)";
  sas_pattern := stuple_cons_pattern =># "_1";

  stuple_cons_pattern := stuple_pattern ",," stuple_pattern =>#  // 
<---------------
    "`(pat_tuple_cons ,_sr ,_1 ,_3)";
  stuple_cons_pattern := stuple_pattern =># "_1";

  stuple_pattern := scoercive_pattern ("," scoercive_pattern )* =>#
    "(chain 'pat_tuple _1 _2)";

You can add a new way, or modify the old way, by just changing the relevant 
line.

If you want to change the precedence you have a little more work,
but it shouldn't be hard to see how it works.

> The type system isn't there just to stop you making silly mistakes.
> Its there to *enable* automation.
> 
> Yes, I think this is a more exciting feature in Felix.  

And other languages. Including C++. C++ has a really bad type
system BUT it can do some cool things. Consider the 

        rvalue-binder &&

stuff used to implement linear typing (moving the innards of
a string without copying)


> And it does require more type information so the compiler can work harder, I 
> get that.

Unfortunately, it also has to preserve a lot of type information. The garbage 
collection
method requires a map of where pointers are.

And, the generated C++ has to preserve type information both to allow you 
to understand the generated code (hard!) and also to allow integration
with C++ (templates, overloading, etc).

So unlike some systems which do type-erasure, Felix cannot
do that. Interestingly: Java originally didn't do type erasure because
of the crappy downcasting rubbish which requires run time type
information, and even worse crud, introspection.

But since Sun refused to modify the JVM, to implement the
polymorphism they had to erase the types.

> 
> The bottom line is as I said before: OO does not work.
> It cannot model interesting concepts. It can only model
> very boring simple concepts where a type is characterised
> entirely by properties. (property --> method).
> 
> Well, "does not work" is strong language I'm not sure how to interpret here.  
> Does not work for what?  

Yes, legit complaint. I should specify what it is that I say doesn't work.
That requires backtracking in history: the idea is that we want to be
able to separate abstractions/interfaces from implementations.
We want polymorphism too.

Now, as you know functions hide their implementations.

It ain't called "lambda-abstraction" for nothing :)

But just functions aren't enough. Traditionally they operated on structs
and such like: i.e. the functions may be abstract, the encoding of the
algorithm is abstract but the data structures are concrete.

Woe!

Conceptually we want something that obeys certain rules which Bertand Meyer
explained well in "Object Oriented Software Construction". to me the key
principle is called the Open / Closed Principle. It says you have some unit
of modularity which is closed for use (hey, I finished it!) and also open
for extensions.

Function libraries are easy to extend, and they're easy to use as is,
so they obey this principle BUT they only work for those dang
concrete data structures.

We need to "abstract away" the implementation details of the
data structures too.

In a nutshell we want a notion of "abstract types".

I will come back to this, but there is such a notion of abstraction,
it existed long before OO, and it is rock solid high level mathematics:
its called category theory. It is THE theory of abstraction.

Anyhow, Meyer invented Eiffel, but he made a mistake.

He chose the unit of modularity as the class which represented
a type. The problem is that's just WRONG. 

Classes are fine. Its another name for "category".
A category is a collection of functions. Its completely abstract,
because there are no values to operate on: it uses an
identity function for domains and codomains instead
of sets, and it uses composition instead of application.

This way, the data types are completely eliminated.
Its 100% abstract. The theory is sound.

The key thing is: there's no constraint that there be only
one identity function (type) in a category.

Meyer identified "the one object (type) in a category (class)
with "the type". Its just wrong.

In Felix:

class X[U,V] {   virtual fun f: U -> V; }

the U and V are TWO types of the class, and 
f is a "multi-method".

This is the correct model. A class is a COLLECTION of types
and functions, not a single type. So you cannot identify the
notion of class with type, or you screw up.

the word "class" in German is "kategorie".
Its the same word.

Anyhow, that the goal: to provide ADTs (abstract data types).

By specification "abstract" means "represent by functions".

you can see how OO is an attempt to provide this.

And how you can see that it doesn't and why. Because assuming
a class has only one type in it leads to the covariance problem.
The reality is, classes can have many types.

Felix solution, by the way, is not nearly as powerful
as the one in Ocaml (in which not only types, but also
functions themselves, can be parameters).

> It's working for a lot of people right as I type!

Sure, and I can program in Assembler!

> 
> in Felix it would loook like something like:
> 
>         typedef dimension = Length * Energy * Temperatuire * MagneticFlux ...
> 
> where each of those standard 7 SI units could be 0, 1, 2, ... -1, -2, -3 ...
> 
> Hmm it seems like more work to put all this in place than it is to just test 
> the algorithm.

If you're writing a one off program, that's probably the case. Sure.

Burt now .. would you say the same if I were designing the control
system for a nuclear power plant? Or worse, fly-by-wire for
a domestic airliner?

What about a game? Well actually, whilst games are rarely safety critical
applications .. they're also THE most complex applications on the planet.
Games involve just about every aspect of everything.

Games need the high level stuff more than any other application.
That's why most of them are so bad: because without ultra cool
tools you just cannot write an ultra-cool game. You can do really
great graphics, but the gameplay engine will be lame if you focus
on that because you only have a $20 million budget.

> It is true Felix cannot do C++ virtual function dispatch. It  used to but it 
> was
> a nightmare to maintain and not of much use so I took it out.
> 
> It would be good to put back in.
> 
> Oh, what did it look like?

Like structs with methods, which you can do right now,
only it had inheritance like C++ as well. I.e. you can have
C++ like classes right now, you just don't get any virtual dispatch,
so there's no "virtual function polymorphism". Its not really OO at all.

Putting this back in is easy in theory but hard in practice.
The "method" have to bind to the object scope (as well as their
functional context) which changes the lookup rules. We have to
keep track of "this" (the object).

And then we generate actual C++ class methods.
this increase the system complexity by over 50%.

I went through a phase of "adding everything including
at least two kitchen sinks" and then another phase of
chucking everything I could possibly discard out.

Felix also had builtin finite state automata (regexps) and builtin
GLR parser.

> I guess I have no idea how you are deciding what makes a game "good".

In a strategy game, your opponents should make good strategic choices.
You should have a sane, comprehensible economy, market,
political and military system. You should make high level decisions
and have the computer implement them. You should have tools that
make it easy to have a view of your empire, without being overburdened
by meaningless detail, but without the system being too simplistic,

in most games, for example, the enemy AI works by very bad
play, the computer players get extra resources to compensate,
and they do moronic early rushes. If you can withstand these
early attacks you always win because the AI has no idea of
strategy. It sometimes takes a long time, but i usually win
or lose against 3-1 or better odds against beefed up computer
players in the first 15% of the game, and usually with a fixed
formula.

In fact the way I usually play, the goal is to defeat the 
programmer (not the enemy) by finding flaws in their
gameplay engine, or optimal combinations.

For example I struggle playing the Humans in Starcraft III in
one particular large scenario, against 3 enemies on Hard setting.
I only win about 10% of the time. The game is so badly designed
I can't win AT ALL playing the Zerg against even 2 ordinary level
enemies.

The problem with the game is that you win or lose in the first
10 seconds of the first attack. You're either ready, or you misplaced
an installation by one pixel or started a build 5 seconds too late.
The humans are vastly superior: they can achieve a massive
concentration of fire no other race can do, they can do it early,
and so they can block choke points against massive odds.
So all you need to do is defend, defend, defend, until the
enemy runs out of resources and has to spread out,
and then their defences are production levels are so bad
you can take them apart easily.

To do that: all cruisers. Why? because they have the
most hitpoints, massive firepower, and they STACK
on top of each other which means you can get concentration
of fire and wipe out enemies before they can get off a single
shot.

Everything else is rubbish. What kind of strategy works by
using 100% capital ships, no smaller vessels, no infantry,
nothing. The ground troops are useless, because the
routing is so bad some units run around in circles
and other go half way around the map because the unit
ahead of them is temporarily blocking the path
(that's why air units rule, there's no terrain to get in the way).


> I think the main excuse is peformance and time to market.  Basically these 
> things need to be "good enough".

The downfall of America. Its gone from a country in which the pursuit
of excellence was replaced by any old shit that you could sell ..
and of course now the pigeons come home to roost, because
China can produce "any old shit" much cheaper.
> 
> Better abstraction and a more expressive type system can help reduce the 
> number of bugs, mainly by letting one write fewer lines of code.  But we're 
> not talking an order of magnitude of productivity here.

That's true. Its more like TWO orders of magnitude.

>  If a developer spends 80% of development time debugging, the best you can 
> hope for is a 5x boost if you improve safety.  But the programmer has to 
> spend more time muddling around with the type system to make it check 
> everything properly, fixing the bugs in the their types so to speak, so it 
> wouldn't be that multiple.

You're missing the point. Compare the amount of effort to implement a modest 
algorithm
like say "red-black trees" of ints in C, and then trees of strings, and then 
trees of doubles,
with C++, where you just say

        set<int>
        set<double>
        set<string>

Come on. that's at least THREE orders of magnitude better!

> Warning: I am easily entertained!  

I hope I  have been of service! :)


> You might find the lack of higher order types in these games annoying.
>  
> It has to be an actual strategy game! Not small unit tactics.
> It has to require strategic planning.
> 
> Have you tried playing "go" ?  :-P

Yes, that is a real strategy game. Its too hard for me :)
I do play chess. But I was talking about computer games.
I good chess program can beat me easily.


--
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