On Sep 8, 2006, at 7:32 PM, skaller wrote:
> The reason for = in some places is purely syntactic:
> { .. } is a valid expression. So for functions:
>
> fun f():int { ... }
>
> is not a possible syntax, because it would mean:
>
> fun f(): _apply(int,{ ... })
> ...
>
> If you think this is messy .. heck, I agree!
Oh no, it wasn't another dig on syntax :) I just wanted the structure
to mirror a static code block (i.e., not executable).
> As to overriding and virtual functions: Haskell already
> allows a default definition, doesn't it?
Definitely, but the system isn't 'intelligent' enough to figure out
how to apply the default definition to a complex data type, such as a
recursive Tree, nor is it generally a good idea to assume the
functions defined in a typeclass will work on all primitive types.
It would make the Felix implementation simpler (but not nearly as
convenient) if users were required to explicitly define the typeclass
functions for each instance--though this is a very boring thing to
have to do, C++ users are more inured to such necessities than
spoiled functional programmers :) It might be a neat thing to add a
kind of template definition and if the type doesn't fit give a
warning...
> I used 'virtual' for a reason too: first, you can't just
> write
>
> add: t * t -> t
>
> because the user can't know if this is a curried procedure
> or a function. The distinction is vital, so you need
>
> fun add: t * t -> t;
>
> to say its a function. The problem is .. the syntax is
> already defined, and means:
>
> fun add: t * t -> t = "add($1,$2)";
Sorry about that. I guess I had been working in Haskell and C too
much and forgot I had to add the 'fun.' That default defined syntax
is a bit of a surprise, though.
> Perhaps I should change that .. but the short form is
> very useful for binding libraries. So I threw in
>
> virtual fun: t * t -> t;
>
> as a way to say "this is a signature".
The only reason I wanted to get rid of it was the tainted nature of
'virtual'--it implies it should be overridden in an OO inheritance
way. (This is, of course, not as true with "Modern C++" programmers
today as it was in even the late '90s.) You might also consider
"pure virtual," (no =0 at the end). On the other hand, there may be
a way to consider a typeclass block as a special context and parse it
differently.
>> // subsets
>> typeclass Ord[T] <= Eq[T] { <--suggestion: left-right s <= S
>> ...
>> }
>
> Yeah, very unfortunate that. The logically correct notation
> for x subset y is actually x => y not x <= y, because
>
> x => y means 'x implies y'
Quite correct. In my own notes--following books I've read, of
course--I tend to use the plain "->" as the conditional (or
implication--same thing, different context). As I mentioned before--
this is from something I read though I can't remember where it was
right now--the <= is meant as an ascii emulation of the "little e"--
element of--symbol (not little eta); a <- would be closer but just as
odd-looking. I don't suppose people are very much used to ascii-
pictures in this Time Of Unicode. The "=>" is fine.
> ;( Been toying with TeX operators ..
>
> x \subseteq y
That would be excellent for literate Felix :)
>> Getting type classes for Felix would be difficult, especially if you
>> want multi-parameter type classes. As a start, you do unfortunately
>> have some reading to do. After that we will have to modify the type
>> system to be able to type-check the typeclass.
>
> Why do we have to type check them?
Type classes are an odd construct; similar to v-tables, I guess. To
handle the constraints imposed by a type class in a program you need
three things:
(1) a data table for the type class itself, covering super-classes,
functions in this class and--especially for types defined in the
standard library or external modules--types that are instances of the
class. You need to lug that table around because the type checker
needs it to validate functions which declare a constraint based on
the type class. If you had a function that you wanted to limit to
the types that are instances of Eq, you would say:
fun same[ (Eq[T]) => T] (T * T) -> Bool = { }...
(Note there is more syntax we could figure out. The Haskell syntax is:
same :: (Eq a) => a -> a -> Bool
(2) The type checker needs two things to validate a function: the
aforementioned data table for the type class and an instance table
for the data type itself. To type-check whether a function is valid
you then check whether the type data table corresponds to the
typeclass data table. A simplistic implementation would have a
subclass (say, Ord) carry information from Eq, such as functions, but
it might be better perform unification with recursive lookups.
(3) on a more programmatic level, typeclasses, like variables,
values, functions and everything else, have a scope so you may keep
the typeclass data table in the "class environment" data table, which
is part of the "environment" table.
Of course there may be more efficient ways to go about this--all this
typechecking stuff mostly stays in the compiler except when you have
compiled a library and need to keep the data tables for types and
typeclasses so future programs without reference to the source code
may know the constraints. There is something of an "update" issue,
here but for Felix it shouldn't be a problem because all this type
checking is performed entirely in the compiler itself.
-Pete
-------------------------------------------------------------------------
Using Tomcat but need to do more? Need to support web services, security?
Get stuff done quickly with pre-integrated technology to make your job easier
Download IBM WebSphere Application Server v.1.0.1 based on Apache Geronimo
http://sel.as-us.falkag.net/sel?cmd=lnk&kid=120709&bid=263057&dat=121642
_______________________________________________
Felix-language mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/felix-language