I find it sometimes hard to come up with reasonable single-function typeclass names. If the method name is a regular verb (like get, write, read...), it's easy to do the same thing Gophers do with single-method interfaces - stick an "er" to the back (Getter, Writer, Reader...) an done. But! If the function name is a noun (name, color...) then adding an "er" to the back no longer works. Namer and Colorer sound too weird because these words are no longer proper English.
One solution could be to add a "has" to the front. One then would get things like HasName, HasColor and also it would work for verbs - HasGet and HasWrite for example. Is this a good approach or not? What are recommended ways to name single-function typeclasses that house noun-ish things?
I suggest that having any prefix means a certain thing and having any suffix means a different thing. Additionally, the class prefix/suffix relates to the prefix/suffix on the member function. This convention should be written explicitly somewhere.
For instance,
module Lib.Colour.Class
-- The following convention is followed
-- Let class prefixes denote that the member has a certain attribute
-- or has some state internally manipulatable.
-- Has- abstracts record type, accessed with get<ClassRootName>
-- Is- Things that *are* another type, coereced with as<ClassRootName>
-- Can- Things that are manipulatable in some way, via do<ClassRootName>
-- Let class suffixes denote types who primarily act on other types
-- -er A thing that does something to another type
class HasColour a where
getColour :: a -> Colour
class IsColour a where
asColour :: a -> Colour
class CanColour a where
doColour :: Colour -> a -> a
class Colourer a where
colour :: CanColour b => a -> b -> b
The thing I like most from this convention is the concept of giving different meaning to prefix and suffix. This consideration made me write CanColour
instead of Colourable
, since something that is colorable is thought of as having an internal state that changes.
Regarding the specifics of "color" and "name", note that these nouns are also verbs. You can name people, you can color hair. I don't find adding an -er to either of these at all objectionable for code--especially measured against the gains of a consistent convention. In my example i use the verb form of color for the member function, so i will only ever use "colorer" in class constraints, which seems fine to me.
Now, this convention ultimately will break down at some point, but until it does it should help the user (you) make reasonable guesses on calling conventions when using the library. It should also help guide you when developing new classes.
So this is one suggestion. Among the packages of Hackage, I don't believe there's a clear standard to guide your design. There are some fair criticisms to the premise of this question (found in its comments). However, the intended design does come with precedent. The diagrams
package, for instance, seems to do something exactly like what you are attempting here. It is a well constructed library written by a very well regarded author.
diagrams
uses prefixes: Is- IsName; Has- HasOrigin. It uses suffixes: -ed, Traced; -able, Transformable. Okay, it uses too many, perhaps? It seems to me that a little more self consistency could have been gained with, for instance, HasTrace
as opposed to Traced
.
So whatever the standard you adopt, since there is no clear consensus of how to do it, you should at least strive for self-consistency of names to concepts and clearly spell out in comments the adopted standard.