On 15/08/2012, at 4:03 AM, Dobes Vandermeer wrote:

> 
> > The headtail() version returns a tuple, which you can pattern match on.
> 
> that cannot work, because you cannot specify the type of "tail"
> or of "head" given a tuple of type T.
> 
> 
> I think it should be possible in general, but maybe something in missing in 
> Felix to support it?

No, its conceptually absurd, in some sense. you cannot apply an operation 
specific to some kind of structure (in this case tuple) without knowing
that the thing is that kind.

If the type is simply "not known at the moment" then you can attempt
to apply the operation when the is known. At that point you will
either succeed, or you will get a type error.

With type classes you defer the operation from "compile" or
binding time (phase one) to "link" or "instantiation" time
(binding, phase two).

Typematch feature in Felix defers things by simply failing
to reduce until reduction is possible.

Value pattern matches cannot do this, so what we do is
"assume" we have a tuple by placing the type in a 
typeclass instance. That instance is only selected at instantiation
time if the type variable actually resolves to a tuple, so the
value match is type safe. If the type doesn't resolve to a tuple
you get a "missing instance" error.

So the type classes provide what in C++ is called "phase two lookup"
and is associated with "dependent names" in templates,
only the typeclass mechanism is good and  the C++ one is rubbish
(it isn't safe because there are no "concepts" to specify the "interface"
required for the type when its a class) Usually in C++ this does NOT
cause a problem, but it can pervert the semantics.


> Ah, I see... how come this didn't cause all sorts of other problems?  For 
> example, if you use that enum for something and try to match against the 
> missing parts of it?

It did cause these problems. But Felix has the C++ approach: its only an error 
if you use it.
It doesn't check for completeness or correctness for "features you don't 
actually use".

So you only get a failure if you actually construct a test case.
[Feiix is designed to do rapid prototyping, similar to dynamic language,
without needing to do dynamic typing unless it is actually necessary]

In fact there really was such a test case for mmap() which worked on Linux
and failed on OSX. That's how I found out about it, and I had to remove
the auto-generated code.

This kind of thing CAN be supported, we just need to tell the compiler
when to do it. 

In Haskell you can do this for "str" and "eq", you can tell the compiler
to autogenerate those operations (only). Its a useful special case.
Its not good enough (because it only works for str and eq) but better
than hand rolling every str and eq on every complicated type
if the compiler generated one would be good enough.

By far the best way to "autogenerate" things is .. DONT!
Put it in the library!!

Do you understand the need for very high order typing
and kinding systems? Its so we can move many of these
auto-generated things out of the compiler and into the
library.

It's not a matter of type checking. That's the confusion many people
have when they think the casting or whatever crud you need to do 
in OO is a good workaround.

In higher order systems, we're not interested much in type *checking*.
We're interested in using type and kind information to *automate*
certain kinds of operations.

The type system isn't there just to stop you making silly mistakes.
Its there to *enable* automation.

Overloading is a good example because its familiar.
The parameter type of a function isn't declared and matched
with the used argument type "just to check you use the right
type". No, its actually used to **select** an appropriate function.
The program wouldn't work at all in the absence of type information,
because there's be no way to choose the right function.

> You're using Java terminology I'm not familiar with.
> 
> Ah, I thought you knew Java to some degree and thus your license to complain 
> about it.  

I do, to some degree. I actually got an HD in Java programming at Uni without 
every
having written any Java. (Well not much anyhow).

I studied Java as part of an ISO body as well.

Yes, I did write some Java once (in the old days, playing
with AWT 1.0 or something).

But I don't know a lot of the nitty gritty details because they
don't really matter for understanding the language system
as a whole.

> Actually I think stack overflows probably are not checked statically by 
> anyone.

In a general (turing complete) language this hard to do.
Some languages, however, cannot stack overflow, and most,
if you have suitable restrictions (eg no recursion) also can't
overflow (you can actually calculate the required stack size).

In the old days many games were like that.

> How do you code unions (sum types) in Java?
> 
> That what the whole class system is for!  A class is the union of its 
> subclasses.

No it isn't. You see,  that's the problem. Classes have two utterly distinct 
unrelated
uses, one legitimate, and one completely fraudulent.

Classes in OO language are supposed to provide abstraction.
A derived class is supposed to be a subtype.

Using a base as a union type with the derived classes as
the components and RTTI for  the discriminant is common
practice but it is completely wrong.

Unification (as in the sense of a union "unifying" distinct types)
has nothing whatsoever to do with subtyping.

It's used for that because the language doesn't provide a proper union.

here a simple proof it doesn't work:

        union Result = | Square of double | Round of double

WOOPS! You cannot do it with casts and objects because there
are TWO cases but only one type.

You can NOT use RTTI as a type constructor (Square, Round
are type constructors). It doesn't work.

C++ BOOST variant made this stupid mistake too.

Heck, so did I, until I learned some theory (and a real language,
in my case Ocaml).

This may sound trivial but it is not. It confuses the heck out
of OO programmers that they have to use classes/object
for two distinct kinds of things, only they don't actually
recognise it.

Let me say again: a SUM of type is NOTHING AT ALL TO
DO WITH SUBTYPING.

NOTHING. ZERO. UNRELATED COMPLETELY.

Sum types add ANY unrelated types together to make
a single type.

Subtyping is nothing more than a subset of the values
of a type.

Inheritance is typically designed for subtyping NOT unification.
[In Ocaml, its much better: subtyping is structural not nominal,
so you do not need to "derive" subtypes as you must do
in Java and C++]

> 
> They don't have a match statement, instead of you have to define methods on 
> the superclass that do the work.  This is an area where Java starts to break 
> down,

No, its an area where ALL OBJECT ORIENTATION breaks down.

Its not a problem in Java as such. Its a problem with the whole
idea of Object Orientation.

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

> the lack of match.  Scala addresses this problem, which is nice, although 
> Scala has other problems that are quite severe.  Like have to perform black 
> magic to make your own collection class.

Really? Didn't know that. -1 for Scala :)

> A trivial example: in physics you know if your formula is likely to be
> correct, because you can apply dimensional analysis.

Any compiler with a good type system can do this.
It can be done in Haskell and in Ocaml.
Not sure about Felix, but it will.

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

Dimensional correctness is then just a matter of defining operations
which say add double value AND add the types. Adding the types
is a constraint that the types are equal. Multiplication adds the integer
values of the types (metres * metres = metres ^ 2).

So the analysis is basically a logarithmic calculation chained together
with the value calculation (with the compiler doing the type calculation).

This is real easy to do in C++ using templates because you can
have integer arguments to templates. Felix should be able to
do it too (but can't at the moment because sum types can't be added).

In other words .. the compiler does not need to have this built in.
It can be done just with user library code.

> The behavior tree is hetergeneous, though ... so it would be a pain to do in 
> Felix compared to C++.  In C++ I would make a common base class with virtual 
> methods.

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.

> 
> If you think current games are using good technology and achieving
> good results ... well you haven't played very many games.
>  
> I haven't just played many games I have programmed them.  Maybe you're the 
> one who is out of touch.

Not at all.  I've played a lot of games and most of them are utter rubbish.
I also ran a game programming company at one time.

I mean, the game "engines" are so completely and utterly primitive
the games aren't worth playing. The interfaces are so lame they
constrain game play so badly that you end up fighting the
game programmer instead of the NPCs :)

Games have got more reliable, and there's no doubt graphics
and motion have improved a lot (although I'm more interested
in games for people over 14).

But the AI? Strategy? Are you kidding? Most games can't
even do basic routing. Heck, that's so well understood
many people have a GPS in their car that can do that.
My yacht navigation computer can do it (though not very well).

Routing is a hard problem, but thats no excuse for the utterly
lame routing algorithms used in most games.

Why is that? because the programmers spend most of their
time either doing pretty graphics (instead of working on the game
logic) or finding bugs, they don't have any time to actually
work on the game engine.

My challenge: show me one good strategy game.
I'll go out and buy it.

It has to be an actual strategy game! Not small unit tactics.
It has to require strategic planning.

There are quite a few "so called strategy games" out there.
Some are simply not strategy games at all.

Some actually are strategy games but they involve fighting
some really lame strategic model and one soon figures
out how to break it.

Until it stopped working I played Europa Universalis.
At least that was hard, and it had a reasonably good strategic
model (but unfortunately the trading model sucked big time).
I think that's the best strategy game I ever played (solo).

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