Re: [Haskell-cafe] Inheritance and Wrappers
On 3 February 2011 02:35, Brandon Moore brandon_m_mo...@yahoo.com wrote: Here's one thing to consider: Can you write a function f :: (Data a) = a - String f x = termTag x It would seem the Data a = Term a instance justifies this function, and it will always use the default instance. Now, what happens if f is applied to a value of some type T which is an instance of Data, but has a custom Term instance? Great point, thanks! I guess somehow you shouldn't be allowed to write that function f. I need to think about this one. -- Ozgur ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Inheritance and Wrappers
OK, what about this as a use case then. I want to create a type class 'Term' with only one function in it. The function returns a 'termTag' which labels the kind of a value in a DSL. class Term a where termTag :: a - String A user of this type-class can happily provide an instance without any other type class requirement. However, I want those types which are instances of Data to be an instance of Term automatically. On top of that, I don't want to stop the user from creating a special instance for their data type. I want to be able to write the following instance to accomplish that: instance Data t = Term t where termTag = show . toConstr A much more predictable option is to provide this default implementation as a function termTagData :: (Data t) = (t - String) and let the library clients use it in their instances if the behavior is fine: instance Term MyT where termTag = termTagData And if the user wants to write a more specific instance, they should be welcome to do so: instance Term UserDT where termTag (...) = ... I am not very much interested in the technical details about how things currently are, I am more interested in a discussion about why (if?) this would be considered a design flaw? Here's one thing to consider: Can you write a function f :: (Data a) = a - String f x = termTag x It would seem the Data a = Term a instance justifies this function, and it will always use the default instance. Now, what happens if f is applied to a value of some type T which is an instance of Data, but has a custom Term instance? Brandon. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Inheritance and Wrappers
From: Steffen Schuldenzucker sschuldenzuc...@uni-bonn.de On 01/31/2011 08:58 PM, MattMan wrote: [...] data Wrapper a = Wrap a instance (Num a) = AbGroup (Wrapper a) where add (Wrap i) (Wrap j) = Wrap(i+j) However, this is clumsy. Is there something else I can do? Thanks This is the normal approach. You can do funny things with the OverlappingInstances extension, but it is probably not what you want. The problem is that the compiler only considers the heads of the instance declarations when determining which instance to use for a specific type. So an instance like this: instance (Num a) = AbGroup a where ... means: Some type matching 'a' (that is, any type) is an instance of 'AbGroup' if and only if it is an instance of 'Num'. I would word this differently. I would say this instance means: Some type matching 'a' (that is, any type) is an instance of 'AbGroup'. It is an error to use AbGroup methods if 'a' does not have a Num instance in scope. The important point is that this declares an AbGroup instance for every type, not just types with Num instances. Which means that this instance is much less useful than you would hope. I would probably use either Henning's approach of separate functions or an automatic deriving mechanism. I've never understood why Haskellers are so averse to writing new instances anyway. John ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Inheritance and Wrappers
On 1 February 2011 11:41, John Lato jwl...@gmail.com wrote: The important point is that this declares an AbGroup instance for every type, not just types with Num instances. So, is there a way to declare an AbGroup instance for the types with num instances only? Thanks, Ozgur ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Inheritance and Wrappers
On 1 February 2011 11:47, Ozgur Akgun ozgurak...@gmail.com wrote: So, is there a way to declare an AbGroup instance for the types with num instances only? No - as Henning says its then no more useful than simply a function: add :: (Num u) = a - a - a add = (+) 'Overarching instances' i.e. classes with one implementation are a design flaw, not a virtue [*] so this hypothetical extension isn't welcome... {-# LANGUAGE OverarchingInstances #-} [*] Of course, there might be some valid cases for things in Oleg Kiselyov's typecast style, but modelling numericals doesn't look like one of them. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Inheritance and Wrappers
OK, what about this as a use case then. I want to create a type class 'Term' with only one function in it. The function returns a 'termTag' which labels the *kind* of a value in a DSL. class Term a where termTag :: a - String A user of this type-class can happily provide an instance without any other type class requirement. However, I want those types which are instances of Data to be an instance of Term automatically. On top of that, I don't want to stop the user from creating a special instance for their data type. I want to be able to write the following instance to accomplish that: instance Data t = Term t where termTag = show . toConstr And if the user wants to write a more specific instance, they should be welcome to do so: instance Term UserDT where termTag (...) = ... I am not very much interested in the technical details about how things currently are, I am more interested in a discussion about why (if?) this would be considered a *design flaw*? Best, On 1 February 2011 12:18, Stephen Tetley stephen.tet...@gmail.com wrote: On 1 February 2011 11:47, Ozgur Akgun ozgurak...@gmail.com wrote: So, is there a way to declare an AbGroup instance for the types with num instances only? No - as Henning says its then no more useful than simply a function: add :: (Num u) = a - a - a add = (+) 'Overarching instances' i.e. classes with one implementation are a design flaw, not a virtue [*] so this hypothetical extension isn't welcome... {-# LANGUAGE OverarchingInstances #-} [*] Of course, there might be some valid cases for things in Oleg Kiselyov's typecast style, but modelling numericals doesn't look like one of them. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe -- Ozgur Akgun ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Inheritance and Wrappers
On Tue, Feb 1, 2011 at 11:47 AM, Ozgur Akgun ozgurak...@gmail.com wrote: On 1 February 2011 11:41, John Lato jwl...@gmail.com wrote: The important point is that this declares an AbGroup instance for every type, not just types with Num instances. So, is there a way to declare an AbGroup instance for the types with num instances only? Not to my knowledge. John ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Inheritance and Wrappers
On Tuesday 01 February 2011 13:45:34, Ozgur Akgun wrote: I want to be able to write the following instance to accomplish that: instance Data t = Term t where termTag = show . toConstr And if the user wants to write a more specific instance, they should be welcome to do so: instance Term UserDT where termTag (...) = ... I am not very much interested in the technical details about how things currently are, I am more interested in a discussion about why (if?) this would be considered a *design flaw*? I think the strongest reason to consider it a design flaw is the current implementation, that instance selection doesn't take contexts into account. Things being as they are, an instance A a = B a where ... just isn't very useful. If instance selection took contexts into account, such an instance might be useful, but it would still prevent users from declaring instances for both classes (without an extension which would have much the same problems as OverlappingInstances). ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Inheritance and Wrappers
On 1 February 2011 12:45, Ozgur Akgun ozgurak...@gmail.com wrote: I am not very much interested in the technical details about how things currently are, I am more interested in a discussion about why (if?) this would be considered a design flaw? Wanting a general base case + specific exceptional cases is in no way heinous. However this is somewhat at odds with type-class resolution as it stands. SYB3 is a one of systems to reconcile the problem. [By the way, this needs interpreting with a large grain of salt. I haven't been following the Generics story much recently, so I could be mis-representing things, nor do I have a particularly sound knowledge of how GHC resolves overlapping...] ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] Inheritance and Wrappers
tldr: Can I make arbitrary instances of one class instantiate another without using wrappers? I'm new to Haskell, and am trying to implement some simple typeclasses for doing algebra. For example I have type class (simplified for the sake of argument) class AbGroup a where add :: a - a - a I would like any type instantiating Num to also be an abelian group: instance (Num a) = AbGroup a where add i j = i+j, but this doesn't compile because a is a variable, not a type constructor(or something). The problem is fixed, in a sense, If I introduce a wrapper class data Wrapper a = Wrap a instance (Num a) = AbGroup (Wrapper a) where add (Wrap i) (Wrap j) = Wrap(i+j) However, this is clumsy. Is there something else I can do? Thanks! -- View this message in context: http://haskell.1045720.n5.nabble.com/Inheritance-and-Wrappers-tp3365126p3365126.html Sent from the Haskell - Haskell-Cafe mailing list archive at Nabble.com. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Inheritance and Wrappers
On 01/31/2011 08:58 PM, MattMan wrote: [...] data Wrapper a = Wrap a instance (Num a) = AbGroup (Wrapper a) where add (Wrap i) (Wrap j) = Wrap(i+j) However, this is clumsy. Is there something else I can do? Thanks This is the normal approach. You can do funny things with the OverlappingInstances extension, but it is probably not what you want. The problem is that the compiler only considers the heads of the instance declarations when determining which instance to use for a specific type. So an instance like this: instance (Num a) = AbGroup a where ... means: Some type matching 'a' (that is, any type) is an instance of 'AbGroup' if and only if it is an instance of 'Num'. An additional instance like instance AbGroup SomeData where ... would then conflict with the instance above: As 'SomeData' in particular matches the type 'a', the compiler does not know which one to choose. You could argue that the latter is more specific than the former, so the compiler should choose that one. This is exactly what OverlappingInstances does, but it can have more, unwanted effects. You can make your wrapper code less clumsy by deriving some instances such as {-# LANGUAGE GeneralizedNewtypeDeriving #-} data Wrapper a = Wrap a deriving (Eq, Ord, Read, Show, Num) -- Steffen ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Inheritance and Wrappers
On Monday 31 January 2011 20:58:02, MattMan wrote: tldr: Can I make arbitrary instances of one class instantiate another without using wrappers? I'm new to Haskell, and am trying to implement some simple typeclasses for doing algebra. For example I have type class (simplified for the sake of argument) class AbGroup a where add :: a - a - a I would like any type instantiating Num to also be an abelian group: instance (Num a) = AbGroup a where add i j = i+j, but this doesn't compile because a is a variable, not a type constructor(or something). The problem is fixed, in a sense, If I introduce a wrapper class data Wrapper a = Wrap a instance (Num a) = AbGroup (Wrapper a) where add (Wrap i) (Wrap j) = Wrap(i+j) However, this is clumsy. Is there something else I can do? Thanks! Not really. You could enable the FexibleInstances extension, then your first instance would compile. But it would mean 'every type is an instance of AbGroup, and if you try to use it with something that isn't also a Num, it won't compile, also you can't have any other instances', not what you want. You could then also enable OverlappingInstances, which would allow you to write other instances, but that extension is widely regarded as dangerous (have to confess, I forgot what the dangers were, one was that instance selection doesn't always do what you want/expect). Wrapper instances or specific instances are probably the best way (specific instances to be generated by a preprocessor or TH). ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Inheritance and Wrappers
-BEGIN PGP SIGNED MESSAGE- Hash: SHA1 On 1/31/11 15:24 , Daniel Fischer wrote: want. You could then also enable OverlappingInstances, which would allow you to write other instances, but that extension is widely regarded as dangerous (have to confess, I forgot what the dangers were, one was that instance selection doesn't always do what you want/expect). Instance selection will still not look at the context, so multiple instances would complain about needing IncoherentInstances, and if you add *that* then it does something like taking the first matching instance it finds (again, ignoring the context completely). - -- brandon s. allbery [linux,solaris,freebsd,perl] allb...@kf8nh.com system administrator [openafs,heimdal,too many hats] allb...@ece.cmu.edu electrical and computer engineering, carnegie mellon university KF8NH -BEGIN PGP SIGNATURE- Version: GnuPG v1.4.11 (Darwin) Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org/ iEYEARECAAYFAk1HHNMACgkQIn7hlCsL25XFYgCgqLWUoZzYrZO54ydDY9kTa9RT 3VAAn0WgJzeWO5vvO4QP1pkEYL5tzxYB =+6Pz -END PGP SIGNATURE- ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Inheritance and Wrappers
On Mon, 31 Jan 2011, MattMan wrote: I'm new to Haskell, and am trying to implement some simple typeclasses for doing algebra. For example I have type class (simplified for the sake of argument) class AbGroup a where add :: a - a - a I would like any type instantiating Num to also be an abelian group: instance (Num a) = AbGroup a where add i j = i+j, If all methods of AbGroup can be defined for all Num types - why do you want an AbGroup at all? You could simply write functions with Num constraint. You may be also interested in existing approaches to algebra in Haskell: http://www.haskell.org/haskellwiki/Mathematical_prelude_discussion ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Inheritance and Wrappers
On Mon, 31 Jan 2011, Brandon S Allbery KF8NH wrote: On 1/31/11 15:24 , Daniel Fischer wrote: want. You could then also enable OverlappingInstances, which would allow you to write other instances, but that extension is widely regarded as dangerous (have to confess, I forgot what the dangers were, one was that instance selection doesn't always do what you want/expect). Instance selection will still not look at the context, so multiple instances would complain about needing IncoherentInstances, and if you add *that* then it does something like taking the first matching instance it finds (again, ignoring the context completely). Since the original poster classified himself as new to Haskell, I'm afraid that advanced and dangerous extensions are not the appropriate answer. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Inheritance and Wrappers
\quote Henning Thielemann wrote: If all methods of AbGroup can be defined for all Num types - why do you want an AbGroup at all? You could simply write functions with Num constraint. Well, I'd rather not have to implement (*), abs, etc on every abelian group. You may be also interested in existing approaches to algebra in Haskell: http://www.haskell.org/haskellwiki/Mathematical_prelude_discussion Yes, in fact I am! Thanks for the suggestion; it seems numeric-prelude does [most of] the things I want. Thanks all. -- View this message in context: http://haskell.1045720.n5.nabble.com/Inheritance-and-Wrappers-tp3365126p336.html Sent from the Haskell - Haskell-Cafe mailing list archive at Nabble.com. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe