Jump to content
Main menu
Main menu
move to sidebar
hide
Navigation
Haskell
Wiki community
Recent changes
Random page
HaskellWiki
Search
Search
Create account
Log in
Personal tools
Create account
Log in
Pages for logged out editors
learn more
Contributions
Talk
Editing
Context alias
(section)
Page
Discussion
English
Read
Edit
View history
Tools
Tools
move to sidebar
hide
Actions
Read
Edit
View history
General
What links here
Related changes
Special pages
Page information
Warning:
You are not logged in. Your IP address will be publicly visible if you make any edits. If you
log in
or
create an account
, your edits will be attributed to your username, along with other benefits.
Anti-spam check. Do
not
fill this in!
==== Class aliases with new methods ==== I would like to emphasize an important point from the original proposal that was not emphasized enough: Lets look at one of the examples from the original proposal: class SemiLatticeJoin a where join :: a -> a -> a class BoundedBelow a where bottom :: a class BoundedBelowJoinable a = (BoundedBelow a, SemiLatticeJoin a) where joins :: [a] -> a joins xs = foldl join bottom xs Notice that ''BoundedBelowJoinable'' doesn't have the ''alias'' keyword. Is this a syntax error or is it allowed? It is allowed because ''BoundedBelowJoinable'' is not just an alias for ''(BoundedBelow a, SemiLatticeJoin a)''. It also declares a new method called ''joins''. So why is this usefull? Users can declare instances for ''BoundedBelow'' and ''SemiLatticeJoin'' and get ''joins'' for free or they can declare an instance for ''BoundedBelowJoinable'' and define an optimized ''joins'' for their type. Lets look at another example why this ability, to give a class alias new methods, is useful. Again I take an example from the original proposal but I slightly change it: The current ''Num'' class in the Prelude is (more or less) this class Num a where (+) :: a -> a -> a (*) :: a -> a -> a (-) :: a -> a -> a negate :: a -> a fromInteger :: Integer -> a Ideally we would want to split it up using classes from the [http://hackage.haskell.org/cgi-bin/hackage-scripts/package/monoids monoids package]: class Monoid a where mempty :: a mappend :: a -> a -> a class Monoid a => Group a where gnegate :: a -> a minus :: a -> a -> a gsubtract :: a -> a -> a gnegate = minus mempty a `minus` b = a `mappend` gnegate b a `gsubtract` b = gnegate a `mappend` b class Multiplicative a where one :: a times :: a -> a -> a class FromInteger a where fromInteger :: Integer -> a But this creates some problems as mentioned in the proposal: * People using the new prelude have to write the ungainly (Monoid a, Group a, Multiplicative a, FromInteger a) and declare separate instances for all of them. * If at some point a HasZero class is separated out then everyone needs to modify their instance declarations. * Num still must be declared if you want it to work with old prelude functions, containing completely redundant information. * All the problems mentioned in the second section of the proposal about alternate preludes in general. We can solve all of them by creating a class alias: class alias Num a = (Monoid a, Group a, Multiplicative a, FromInteger a) Or can we? Unfortunately this ''Num'' is different than the original ''Num''. Because instead of the methods ''(+)'', ''(-)'', ''(*)'' and ''negate'' we have ''mappend'', ''minus'', ''times'' and ''gnegate''. Fortunately we can add the original names as new methods to the class alias and give them default definitions in terms of the new names: class Num a = (Monoid a, Group a, Multiplicative a, FromInteger a) where -- Default implementations of existing methods: mempty = 0 mappend = (+) one = 1 times = (*) minus = (-) gnegate = negate -- New methods with default implementations: (+) :: a -> a -> a (+) = mappend (*) :: a -> a -> a (*) = times (-) :: a -> a -> a (-) = minus negate :: a -> a negate = gnegate The question is: how is the above translated? The new methods from ''Num'' should be placed in a new "internal" class: ''Num_NEW_METHODS'': class Num_NEW_METHODS a where (+) :: a -> a -> a (*) :: a -> a -> a (-) :: a -> a -> a negate :: a -> a What happens when a user defines an instance for ''Num''? Lets look at an example: Say a user defines the natural numbers and makes them an instance of the ''Num'' class alias: data N = Z | S N instance Num N where Z + y = y S x + y = S (x + y) Z * _ = Z S Z * y = y S x * y = y + x * y x - Z = x S x - S y = x - y fromInteger 0 = Z fromInteger (n+1) = S n -- You gotta love n+k patterns! Note that the other methods of ''Num'' like ''mempty'', ''mappend'', ''one'' and ''times'' have default implementations in terms of the above. First of all an instance for ''Num_NEW_METHODS'' will be defined: instance Num_NEW_METHODS N where Z + y = y S x + y = S (x + y) Z * _ = Z S Z * y = y S x * y = y + x * y x - Z = x S x - S y = x - y negate = gnegate Then the other instances are defined using methods from ''Num_NEW_METHODS'': instance Monoid N where mempty = 0 mappend = (+) instance Group N where minus = (-) instance Multiplicative N where one = 1 times = (*) instance FromInteger N where fromInteger 0 = Z fromInteger (n+1) = S n -- You gotta love n+k patterns! In conclusion, a class alias is a name for a context plus optionally a new class. The question is how useful this ability is. The ''BoundedBelowJoinable'' could also be defined as a normal class with the necessary superclasses: class (BoundedBelow a, SemiLatticeJoin a) => BoundedBelowJoinable a where joins :: [a] -> a joins xs = foldl join bottom xs However, user now don't get a ''BoundedBelowJoinable'' for free when they have defined instances for ''BoundedBelow'' and ''SemiLatticeJoin''.
Summary:
Please note that all contributions to HaskellWiki are considered to be released under simple permissive license (see
HaskellWiki:Copyrights
for details). If you don't want your writing to be edited mercilessly and redistributed at will, then don't submit it here.
You are also promising us that you wrote this yourself, or copied it from a public domain or similar free resource.
DO NOT SUBMIT COPYRIGHTED WORK WITHOUT PERMISSION!
Cancel
Editing help
(opens in new window)
Toggle limited content width