Re[2]: "class []" proposal Re: [Haskell-cafe] One thought: Num to 0as ? to list?
Hello Arie, Tuesday, August 22, 2006, 8:24:17 PM, you wrote: >> data Object = forall a. Object a => Object a > I like the idea of separating class and type constructor namespaces, and > then being able to use existentials as in your example (although the > latter would also belong in the category "not nice to beginners struggling > with discriminating type constructors, data constructors and classes"). > On the other hand, I find Bulat's proposal also very attractive, > especially when considering the important example of the list type. > The question is essentially: what do we want to express when writing > things like: > f :: Object -> Object > g :: Object -> Object -> Ordering > h :: Object -> Object -> Object > i :: Int -> Object > ? Is the argument of 'f' an 'Object' of the same concrete type as the > result (Bulat's proposal)? Or do we only demand that they are both an > object, possibly implemented in different ways (using sloppy OO language)? my proposal is modeled after real situations. i found than in most cases when some class is used two times or more in function signature, it should be the same type. existential types, suggested by Brian, rather rarely used in Haskell. may be it's just because there is no good syntax, but i think than in most cases polymorphic types are just enough > k :: Garage -> Car > type Garage = Car -> Car > Bulat's proposal (if suitably extended to apply to type synonyms as well) > would not allow you to substitute the definition of 'Garage' (which would > then be equivalent to 'type Garage = forall a. (Car a) => a -> a') in the > type signature of 'k' (because then the 'Car' of the 'Garage' definition > would suddenly be unified with the result type of 'k'). you are right here -- Best regards, Bulatmailto:[EMAIL PROTECTED] ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re[2]: "class []" proposal Re: [Haskell-cafe] One thought: Num to 0as ? to list?
Hello Brian, Tuesday, August 22, 2006, 9:35:21 PM, you wrote: > I feel "if it ain't broken don't fix it", and not only is the existing > syntax not broken, it's already (imho) absolutely perfect in it's clarity > and consistency it's because you not programmed a lot with type classes. if you start, you will soon realize that type signatures with classes are just unreadable. just look at sources of my streams library -- Best regards, Bulatmailto:[EMAIL PROTECTED] ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: Re[2]: "class []" proposal Re: [Haskell-cafe] One thought: Num to 0as ? to list?
Bulat Ziganshin wrote: f :: Num a => a -> Int write as f :: Num -> Int so, while this proposal is rather minor, i think that it is Good thing I wouldn't like it because I'd like to eventually make the class namespace separate from the tycon namespace so that I could write: class Object a where ... data Object = forall a. Object a => Object a etc (this goes with H' proposal that the namespace should always be explicit on the module export/import list [1]). A good editor (hint: the one I'm writing!!!) will be able to highlight the uses of "Object" to make it clear which is a class, which is a Tycon, and which is a ValueCon, and the operation of replacing a concrete type with a class in the type signature to generalise some functions could be made easier with a good refactoring tool. Best regards, Brian. [1] http://hackage.haskell.org/trac/haskell-prime/wiki/TagExportsWithNamespace -- Logic empowers us and Love gives us purpose. Yet still phantoms restless for eras long past, congealed in the present in unthought forms, strive mightily unseen to destroy us. http://www.metamilk.com ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: Re[2]: "class []" proposal Re: [Haskell-cafe] One thought: Num to 0as ? to list?
Bulat Ziganshin wrote: from one my module: copyStream :: (BlockStream h1, BlockStream h2, Integral size) => h1 -> h2 -> size -> IO () in my library and found the way to simplify most of their signatures: copyStream :: BlockStream* -> BlockStream** -> Integral -> IO () i think that second block of signatures is an order of magnitude more readable I think template haskell could do this translation. Eg if you declared some dummy phantom types so the arg to the template function could be parsed, and as a way of telling the function which types were to be replaced by type variables with class constraints the block of signatures would just be declared in a splice: $(expandSigs [d| data BlockStream' data BlockStream'' data Integral' copyStream :: BlockStream' -> BlockStream'' -> Integral' -> IO () ... |]) Though I leave the definition of expandSigs :: Q [Dec] -> Q () as a little exercise for the reader... :-) Best regards, Brian. -- Logic empowers us and Love gives us purpose. Yet still phantoms restless for eras long past, congealed in the present in unthought forms, strive mightily unseen to destroy us. http://www.metamilk.com ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: Re[2]: "class []" proposal Re: [Haskell-cafe] One thought: Num to 0as ? to list?
Bulat Ziganshin wrote: Hello Brian, Tuesday, August 22, 2006, 9:35:21 PM, you wrote: I feel "if it ain't broken don't fix it", and not only is the existing syntax not broken, it's already (imho) absolutely perfect in it's clarity and consistency it's because you not programmed a lot with type classes. if you start, you will soon realize that type signatures with classes are just unreadable. just look at sources of my streams library copyStream :: (BlockStream h1, BlockStream h2, Integral size) => h1 -> h2 -> size -> IO () Here is another possible syntax, which wouldn't conflict with the existing syntax but could be used as a sugar: copyStream :: {BlockStream} h1 -> {BlockStream} h2 -> {Integral} size -> IO () The type variables could be optional if they are distinct (or not needed in the body) so you could write: copyStream :: {BlockStream} -> {BlockStream} -> {Integral} -> IO () The {} is needed to distinguish the use of classes from that of types, and also allows more than one constraint eg: foo :: (Num a, Bar a) => a -> a === foo :: {Num, Bar} a -> a (the constraint(s) just get written before the first occurrence of a given type variable), and it's even possible to represent constraints between type variables eg: foo :: Collection c a => a -> c === foo :: {Collection c} a -> c It's slightly more difficult to know how to represent the following: foo :: Collection c a => c -> c perhaps: foo :: {Collection * a} c -> c where the * represents the location of the variable in the constraint. Even a rank 2 type like: forall a. Num a => (forall b. (Coll b a, Ord b) => b a -> ()) -> () (forall b. {Coll * a, Ord}b{Num}a -> ())-> () ie forall a. (forall b. ({Coll * a, Ord} b) ({Num} a) -> ()) -> () (It doesn't matter how nested the location of the constraints are since we'd just gather them up and use them to restrict the quantification for that variable) Anyway that's as far as I've got trying to think up alternative representations - the above may have some bug or problem with it but I'm half thinking of adding the above sugar to my editor (when I eventally get past all the low-level gui stuff I'm doing at the moment). Best regards, Brian. -- Logic empowers us and Love gives us purpose. Yet still phantoms restless for eras long past, congealed in the present in unthought forms, strive mightily unseen to destroy us. http://www.metamilk.com ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: Re[2]: "class []" proposal Re: [Haskell-cafe] One thought: Num to 0as ? to list?
> > it's because you not programmed a lot with type classes. if you > > start, you will soon realize that type signatures with classes are > > just unreadable. just look at sources of my streams library > > copyStream :: (BlockStream h1, BlockStream h2, Integral size) >=> h1 -> h2 -> size -> IO () I know this is probably just a personal preference, but I have to say that this syntax (the canonical Haskell'98 one) is by far the most readable and instantly clear of any of the alternatives that have been suggested in this thread: copyStream :: BlockStream* -> BlockStream** -> Integral -> IO () Here you have invented a new notation for type variables (* and **), when we already have a perfectly good one. copyToMemoryStream :: BlockStream -> MemoryStream -> Integral -> IO () Whereas here, the lack of any type variable means I am no longer aware that overloading is going on. This is likely to discourage the reuse of this code fragment, rather than encourage it. copyStream :: {BlockStream} h1 -> {BlockStream} h2 -> {Integral} size -> IO () What is gained by attaching the constraints inline with the type variables? If the type variable occurs more than once, which occurrence should I attach the constraint to? What if I attach different constraints to different occurrences of the same variable? (Obviously the union is intended, but writing constraints in several different locations would be highly confusing). But at least there is a syntactic marker ({}) that overloading is happening. copyStream :: {BlockStream} -> {BlockStream} -> {Integral} -> IO () Again, omitting type variables means that the possible mental confusion over whether the two {BlockStream} constraints apply to the same implicit variable or to different ones is unpleasant. Better to be fully explicit, after all, it only takes one extra character to name the variable! > foo :: Collection c a => a -> c > === foo :: {Collection c} a -> c > > foo :: Collection c a => c -> c > === foo :: {Collection * a} c -> c > > forall a. Num a => (forall b. (Coll b a, Ord b) => b a -> ()) -> () > === (forall b. {Coll * a, Ord}b{Num}a -> ())-> () > === forall a. (forall b. ({Coll * a, Ord} b) ({Num} a) -> ()) -> () The lengths people will go to in making things difficult for the reader, just to save a few characters is truly amazing. Remember, the code will be read many more times than it is written. IMHO, the various proposed sugar adds nothing helpful, and just muddies understanding. Regards, Malcolm ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: Re[2]: "class []" proposal Re: [Haskell-cafe] One thought: Num to 0as ? to list?
On Wed, Aug 23, 2006 at 01:28:57PM +0100, Malcolm Wallace wrote: > The lengths people will go to in making things difficult for the reader, > just to save a few characters is truly amazing. Remember, the code will > be read many more times than it is written. IMHO, the various proposed > sugar adds nothing helpful, and just muddies understanding. Seconded. If someone just wants to type less characters, the he/she can omit most of type signatures. I haven't used any IDE for Haskell (like VisualHaskell), but it would be nice if it could fill the missing type signatures automatically. In cases when monomorphism restriction kicks in, it could also present the type that would be inferred with MR turned off. Best regards Tomasz ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: Re[2]: "class []" proposal Re: [Haskell-cafe] One thought: Num to 0as ? to list?
tomasz.zielonka: > On Wed, Aug 23, 2006 at 01:28:57PM +0100, Malcolm Wallace wrote: > > The lengths people will go to in making things difficult for the reader, > > just to save a few characters is truly amazing. Remember, the code will > > be read many more times than it is written. IMHO, the various proposed > > sugar adds nothing helpful, and just muddies understanding. > > Seconded. If someone just wants to type less characters, the he/she > can omit most of type signatures. > > I haven't used any IDE for Haskell (like VisualHaskell), but it would be > nice if it could fill the missing type signatures automatically. In > cases when monomorphism restriction kicks in, it could also present the > type that would be inferred with MR turned off. I use the following script from vim to infer top level type declarations for me. I've found it particularly useful for understanding others' code: #!/bin/sh # input is a top level .hs decls FILE=$* DECL=`cat` ID=`echo $DECL | sed 's/^\([^ ]*\).*/\1/'` echo ":t $ID" | ghci -v0 -cpp -fglasgow-exts -w $FILE echo $DECL Saved to 'typeOf', you can bind it from vim with: :map ty :.!typeOf %^M in your .vimrc So, from vim the following source: f (x,y,z) a b = y + a + b hit, 'ty' and its replaced with: f :: forall b c a. (Num b) => (a, b, c) -> b -> b -> b f (x,y,z) a b = y + a + b I imagine it would be possible to bind from emacs with little effort. -- Don ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: Re[2]: "class []" proposal Re: [Haskell-cafe] One thought: Num to 0as ? to list?
On Wed, Aug 23, 2006 at 11:11:59PM +1000, Donald Bruce Stewart wrote: > So, from vim the following source: > > f (x,y,z) a b = y + a + b > > hit, 'ty' and its replaced with: > > f :: forall b c a. (Num b) => (a, b, c) -> b -> b -> b > f (x,y,z) a b = y + a + b Nice! Best regards Tomasz ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: Re[2]: "class []" proposal Re: [Haskell-cafe] One thought: Num to 0as ? to list?
On 8/23/06, Donald Bruce Stewart <[EMAIL PROTECTED]> wrote: I use the following script from vim to infer top level type declarationsfor me. I've found it particularly useful for understanding others' code:On the topic of coding Haskell with Vim is there an indentation plugin for Haskell available? Google hasn't found one for me and none ismentioned on the Haskell wiki.Thanks,Toby. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe