Re: [Haskell-cafe] type class design
Hi, sorry for answering to such an old thread. David Menendez d...@zednenem.com writes: On Fri, Oct 29, 2010 at 8:33 AM, Tillmann Rendel ren...@informatik.uni-marburg.de wrote: Hi, Uwe Schmidt wrote: In the standard Haskell classes we can find both cases, even within a single class. Eq with (==) as f and (/=) as g belongs to the 1. case Note that the case of (==) and (/=) is slightly different, because not only can (/=) be defined in terms (==), but also the other way around. The default definitions of (==) and (/=) are mutually recursive, and trivially nonterminating. This leaves the choice to the instance writer to either implement (==) or (/=). Or, for performance reasons, both. While I understand the argument in general, I've never understood why it applies to Eq. Are there any types where it is preferable to define (/=) instead of (==)? Yes for infinite data structures. Cheers, Jean-Marie ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] type class design
On Tue, Dec 21, 2010 at 4:30 AM, Jean-Marie Gaillourdet j...@gaillourdet.net wrote: Hi, sorry for answering to such an old thread. David Menendez d...@zednenem.com writes: On Fri, Oct 29, 2010 at 8:33 AM, Tillmann Rendel ren...@informatik.uni-marburg.de wrote: Hi, Uwe Schmidt wrote: In the standard Haskell classes we can find both cases, even within a single class. Eq with (==) as f and (/=) as g belongs to the 1. case Note that the case of (==) and (/=) is slightly different, because not only can (/=) be defined in terms (==), but also the other way around. The default definitions of (==) and (/=) are mutually recursive, and trivially nonterminating. This leaves the choice to the instance writer to either implement (==) or (/=). Or, for performance reasons, both. While I understand the argument in general, I've never understood why it applies to Eq. Are there any types where it is preferable to define (/=) instead of (==)? Yes for infinite data structures. How so? For an infinite structure, x == y will return False or not return and x /= y will return True or not return. We still have x /= y = not (x == y) and I don't see any reason why one would prefer to define (/=) instead of (==). -- Dave Menendez d...@zednenem.com http://www.eyrie.org/~zednenem/ ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] type class design
On 30 October 2010 22:44, Uwe Schmidt u...@fh-wedel.de wrote: Another possible argument: large type classes can look daunting for both implementors and users, even if only one or two methods need to be defined for a minimal instantiation (I'm tring to work out what to do here myself, as I have some typeclasses that for efficiency reasons it might be nice to have more methods in the class, but it makes it a little overwhelming). But by putting just a small part of the interface into the class does not make the live of a user any simpler. The user usually has to know the whole interface of the module. Or am I missing something? Well, if you have a small class then it's possible for you to split up the different types of functions to be in different modules into more logical sub-types, etc. Also, I find the documentation for the list functions in the Prelude and Data.List easier to read than the ones in ListLike [1], partially because typical documentation for class methods is typically smaller and more compact than the stand-alone functions. [1]: http://hackage.haskell.org/package/ListLike -- Ivan Lazar Miljenovic ivan.miljeno...@gmail.com IvanMiljenovic.wordpress.com ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] type class design
Hi Ivan, Another possible argument: large type classes can look daunting for both implementors and users, even if only one or two methods need to be defined for a minimal instantiation (I'm tring to work out what to do here myself, as I have some typeclasses that for efficiency reasons it might be nice to have more methods in the class, but it makes it a little overwhelming). But by putting just a small part of the interface into the class does not make the live of a user any simpler. The user usually has to know the whole interface of the module. Or am I missing something? Cheers, Uwe ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] type class design
Dear Haskellers, I've a question about type class design. When developing the set of functions for a class, there are often two or more functions, let's say f and g, where the semantics of g can be expressed by f. When writing down the code, there are two choices for g. First g is included in the type class, second g is defined outside and the signature has a context referencing the class. 1. case class Foo a where f :: ... a ... g :: ... a ... g = expr[f] 2. case class Foo a where f :: ... a ... g :: Foo a = ... a ... g = expr[f] What are the reasons for choosing 1., what are the arguments for 2.? My arguments for 1.: a) Efficiency: g may be overwritten in an instance declaration by a more efficient piece of code. b) Readability: All functions, which are logically connected are grouped together in a single syntactic construct and can be found in one place (similar to an interface in Java). My argument for 2.: c) Correctness: The semantics for g are fix (relative to f), All laws for g hold everywhere, assuming f is implemented correctly. I've sometimes the problem to balance the reasons for 1. and 2 and I doubt, that this list of criteria is complete. In the standard Haskell classes we can find both cases, even within a single class. Eq with (==) as f and (/=) as g belongs to the 1. case, so does Monad and (=) as f and () as g. But (=) and the Monad class fall into the 2. case. It seem, there is no uniform or consistent strategy in the core Haskell classes. What are your best practice rules for this problem? Expecting your advices, Uwe ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] type class design
Hi, Uwe Schmidt wrote: In the standard Haskell classes we can find both cases, even within a single class. Eq with (==) as f and (/=) as g belongs to the 1. case Note that the case of (==) and (/=) is slightly different, because not only can (/=) be defined in terms (==), but also the other way around. The default definitions of (==) and (/=) are mutually recursive, and trivially nonterminating. This leaves the choice to the instance writer to either implement (==) or (/=). Or, for performance reasons, both. Tillmann ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] type class design
On 29 October 2010 23:28, Uwe Schmidt u...@fh-wedel.de wrote: Dear Haskellers, I've a question about type class design. When developing the set of functions for a class, there are often two or more functions, let's say f and g, where the semantics of g can be expressed by f. When writing down the code, there are two choices for g. First g is included in the type class, second g is defined outside and the signature has a context referencing the class. 1. case class Foo a where f :: ... a ... g :: ... a ... g = expr[f] 2. case class Foo a where f :: ... a ... g :: Foo a = ... a ... g = expr[f] [snip] My argument for 2.: c) Correctness: The semantics for g are fix (relative to f), All laws for g hold everywhere, assuming f is implemented correctly. Another possible argument: large type classes can look daunting for both implementors and users, even if only one or two methods need to be defined for a minimal instantiation (I'm tring to work out what to do here myself, as I have some typeclasses that for efficiency reasons it might be nice to have more methods in the class, but it makes it a little overwhelming). -- Ivan Lazar Miljenovic ivan.miljeno...@gmail.com IvanMiljenovic.wordpress.com ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] type class design
On Fri, Oct 29, 2010 at 1:33 PM, Tillmann Rendel ren...@informatik.uni-marburg.de wrote: Note that the case of (==) and (/=) is slightly different, because not only can (/=) be defined in terms (==), but also the other way around. The default definitions of (==) and (/=) are mutually recursive, and trivially nonterminating. This leaves the choice to the instance writer to either implement (==) or (/=). Or, for performance reasons, both. I find these sorts of defaults deeply unsatisfying: particularly, suppose I do newtype Foo = Foo Integer deriving (Eq, Show) instance Num Foo where Foo a + Foo b = Foo (a + b) fromInteger = Foo expr = Foo 3 - Foo 2 That I haven't defined implementations for (-) or negate will not even get me a compiler warning, let alone a static error: it will just stack overflow or spin endlessly on expr. This kind of bug is notoriously difficult to track down. I'm not sure how to handle this better, though. A compiler that automatically calculated minimal complete definitions would be nice, but relatively complicated. It might be more sensible to just take all efficiency methods out of classes, and use a mechanism like rewrite rules to give an efficient implementation where possible. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] type class design
On Fri, Oct 29, 2010 at 8:33 AM, Tillmann Rendel ren...@informatik.uni-marburg.de wrote: Hi, Uwe Schmidt wrote: In the standard Haskell classes we can find both cases, even within a single class. Eq with (==) as f and (/=) as g belongs to the 1. case Note that the case of (==) and (/=) is slightly different, because not only can (/=) be defined in terms (==), but also the other way around. The default definitions of (==) and (/=) are mutually recursive, and trivially nonterminating. This leaves the choice to the instance writer to either implement (==) or (/=). Or, for performance reasons, both. While I understand the argument in general, I've never understood why it applies to Eq. Are there any types where it is preferable to define (/=) instead of (==)? -- Dave Menendez d...@zednenem.com http://www.eyrie.org/~zednenem/ ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe