It seems that Frege's ideas about type-classes differ significantly from Haskell. In particular:
The syntax appears to be different, for no obvious reason.
Function types cannot have class instances. (Seems a rather odd rule...)
The language spec says something about implementing superclasses in a subclass instance declaration. (But not if you have diamond inheritance... it won't be an error, but it's not guaranteed to work somehow?)
Frege is less fussy about what an instance looks like. (Type aliases are allowed, type variables are not required to be distinct, etc.)
Methods can be declared as native
, though it is not completely clear what the meaning of this is.
It appears that you can write type.method
to access a method. Again, no indication as to what this means or why it's useful.
Subclass declarations can provide default implementations for superclass methods. (?)
In short, it would be useful if somebody who knows about this stuff could write an explanation of how this stuff works. It's listed in the language spec, but the descriptions are a little bit terse.
(Regarding the syntax: I think Haskell's instance syntax is more logical. "If X is an instance of Y and Z, then it is also an instance of Q in the following way..." Haskell's class syntax has always seemed a bit strange to me. If X implements Eq
, that does not imply that it implements Ord
, it implies that it could implement Ord
if it wants to. I'm not sure what a better symbol would be though...)
Per Ingo's answer:
For example, suppose Foo
is a superclass of Bar
. Suppose each class has three methods (foo1
, foo2
, foo3
, bar1
, bar2
, bar3
), and Bar
provides a default implementation for foo1
. That should mean that
instance Bar FB where foo2 = ... foo3 = ... bar1 = ... bar2 = ... bar3 = ...
should work. But would this work:
instance Foo FB where foo2 = ... foo3 = ... instance Bar FB where bar1 = ... bar2 = ... bar3 = ...
native
in a class declaration, that just sets the default implementation for that method?So if I do something like
class Foobar f where foo :: f -> Int native foo bar :: f -> String native bar
then that just means that if I write an empty instance declaration for some Java native class, then foo
maps to object.foo()
in Java?
In particular, if a class method is declared as native
, I can still provide some other implementation for it if I choose to?
Gottlob Frege was a German logician, mathematician and philosopher who played a crucial role in the emergence of modern logic and analytic philosophy. Frege's logical works were revolutionary, and are often taken to represent the fundamental break between contemporary approaches and the older, Aristotelian tradition.
Russell's paradox is based on examples like this: Consider a group of barbers who shave only those men who do not shave themselves. Suppose there is a barber in this collection who does not shave himself; then by the definition of the collection, he must shave himself. But no barber in the collection can shave himself.
Frege's definition of a number Frege defines numbers as extensions of concepts. 'The number of F's' is defined as the extension of the concept G is a concept that is equinumerous to F. The concept in question leads to an equivalence class of all concepts that have the number of F (including F).
Frege's ontology consisted of two fundamentally different types of entities, namely, functions and objects (1891, 1892b, 1904). Functions are in some sense 'unsaturated'; i.e., they are the kind of thing which take objects as arguments and map those arguments to a value. This distinguishes them from objects.
You seem to have read the language spec very carefully. Great. But, no, type classes/instances do not differ substantially from Haskell 2010. Just a bit, and that bit is notational.
Your points:
ad 1. Yes. The rule is that the constraints, if any, are attached to the type and the class name follows the keyword. But this will change soon in favor of the Haskell syntax when multi param type classes are added to the language.
ad 2. Meanwhile, function types are fully supported. This will be included in the next release. The current release has only support for (a->b), though.
ad 3. Yes. Consider our categoric classes hierarchy Functor -> Applicative -> Monad. You can just write the following instead of 3 separate instances:
instance Monad Foo where
-- implementation of all methods that are due Monad, Applicative, Functor
ad 4. Yes, currently. There will be changes with multi param type classes, however. The lang spec recommends to stay with the Haskell 2010 rules.
ad 5. You'd need that if you model Java Class Hierarchies with type classes. native function declarations are nothing special for type classes/instances. Because you can have an annotation and a default implementation in a class (just as like in Haskell 2010), you can have this in the form of a native declaration, which gives a) the type and b) the implementation (by referring to a Java method).
ad 6. It's orthogonality. Just as you can write M.foo where M is a module, you can write T.foo when T is a type (constructor), because both are namespaces. In addition, if you have a "record", you may need to write T.f x
when Frege cannot infer the type of x
.
foo x = x.a + x.b -- this doesn't work, type of x is unknown
-- remedy 1: provide a type signature
foo :: Record -> Int -- Record being some data type
-- remedy 2: access the field getter functions directly
foo x = Record.a x + Record.b x
ad 7. Yes, for example, Ord has a default implementation for (==) in terms of compare. Hence you can make an Ord instance of something without implementing (==).
Hope this helps. Generally, it must be said, the lang spec needs a) completion and b) updates. If only the day had 36 hours .....
The syntactic issue is also discussed here: https://groups.google.com/forum/?fromgroups#!topic/frege-programming-language/2mCNWMVg5eY
---- Second part ------------
Your example would not work, because, if you define instance Foo FB
then this must hold, irrespective of other instances and subclasses. The default foo1 method in Bar will be used only if no Foo instance exists.
then that just means that if I write an empty instance declaration for some Java native class, then foo maps to object.foo() in Java?
Yes, but it depends on the native declaration, it doesn't have to be an Java instance method of that java class, it could also be a static method or a method of another class, or just a member access, etc.
In particular, if a class method is declared as native, I can still provide some other implementation for it if I choose to?
Sure, just like with any other default class methods. Say a default class method is implemented using pattern guards, that does not mean that you must use pattern guards for your implementation.
Look,
native [pure] foo "javaspec" :: a -> b -> c
just means: please make me a frege function foo
with type a -> b -> c that happens to use javaspec for implementation. (How exactly is supposed to be described in Chapter 6 of the language reference. It's not done yet. Sorry.)
For example:
native pure int2long "(long)" :: Int -> Long
The compiler will see tat this is syntactically a cast operation, and when it sees:
... int2long val ...
it will generate java code like:
((long)(unbox(val))
Apart from that, it will also make a wrapper, so that you can, for example:
map int2long [1,2,4]
The point is that, if I tell you: there is a function X.Y.z, you're not able to tell whether this is a native or a regular one without looking at the source code. Hence, native
is the way to lift Java methods, operators and so forth to the Frege realm. Practically everything that is known as "primOp" in Haskell is just a native function in Frege. For example,
pure native + :: Int -> Int -> Int
(It's not always that easy, of course.)
Every type [constructor] is a namespace. I get how that would be helpful for the infamous named fields problem. I'm not sure why you'd want to declare other things in the scope of this namespace...
It gives you somewhat more control regarding the top namespace. Apart from that, you don't have to define other things there. I just did not see a reason to forbid it once I committed to this simple approach to tackle the record field problem.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With