Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>Alright, there's a lot of confusion about what's happening here floating around, and it's not being helped by the fact that the Haskell term "class" does <em>not</em> line up with the OO term "class" in any meaningful way. So let's try to make a careful answer. This answer starts with Haskell's module system.</p> <p>In Haskell, when you import a module <code>Foo.Bar</code>, it creates a new set of bindings. For each variable <code>x</code> exported by the module <code>Foo.Bar</code>, you get a new name <code>Foo.Bar.x</code>. In addition, you may:</p> <ul> <li>import qualified or not. If you import qualified, nothing more happens. If you do not, an additional name without the module prefix is defined; in this case, just plain old <code>x</code> is defined.</li> <li>change the qualification prefix or not. If you import <code>as Alias</code>, then the name <code>Foo.Bar.x</code> is not defined, but the name <code>Alias.x</code> is.</li> <li>hide certain names. If you hide name <code>foo</code>, then neither the plain name <code>foo</code> nor any qualified name (like <code>Foo.Bar.foo</code> or <code>Alias.foo</code>) is defined.</li> </ul> <p>Furthermore, names may be <em>multiply defined</em>. For example, if <code>Foo.Bar</code> and <code>Baz.Quux</code> both export the variable <code>x</code>, and I import both modules without qualification, then the name <code>x</code> refers to <em>both</em> <code>Foo.Bar.x</code> and <code>Baz.Quux.x</code>. If the name <code>x</code> is never used in the resulting module, this clash is ignored; otherwise, a compiler error asks you to provide more qualification.</p> <p>Finally, if none of your imports mention the module <code>Prelude</code>, the following implicit import is added:</p> <pre><code>import Prelude </code></pre> <p>This imports the <code>Prelude</code> without qualification, with no additional prefix, and without hiding any names. So it defines "bare" names and names prefixed by <code>Prelude.</code>, and nothing more.</p> <p>Here ends the bare basics you need to understand about the module system. Now let's discuss the bare basics you need to understand about typeclasses.</p> <p>A typeclass includes a class name, a list of type variables bound by that class, and a collection of variables with type signatures that refer to the bound variables. Here's an example:</p> <pre><code>class Foo a where foo :: a -&gt; a -&gt; Int </code></pre> <p>The class name is <code>Foo</code>, the bound type variable is <code>a</code>, and there is only one variable in the collection, namely <code>foo</code>, with type signature <code>a -&gt; a -&gt; Int</code>. This class declares that some types have a binary operation, named <code>foo</code>, which computes an <code>Int</code>. Any type may later (even in another module) be declared to be an <em>instance</em> of this class: this involves defining the binary operation above, where the bound type variable <code>a</code> is substituted with the type you are creating an instance for. As an example, we might implement this for integers by the instance:</p> <pre><code>instance Foo Int where foo a b = (a `mod` 76) * (b + 7) </code></pre> <p>Here ends the bare basics you need to understand about typeclasses. We may now answer your question. The only reason the question is tricky is because it falls smack dab on the intersection between two name management techniques: modules and typeclasses. Below I discuss what this means for your specific question.</p> <p>The module <code>Prelude</code> defines a typeclass named <code>Num</code>, which includes in its collection of variables a variable named <code>*</code>. Therefore, we have several options for the name <code>*</code>:</p> <ul> <li><p>If the type signature we desire happens to follow the pattern <code>a -&gt; a -&gt; a</code>, for some type <code>a</code>, then we may implement the <code>Num</code> typeclass. We therefore extend the <code>Num</code> class with a new instance; the name <code>Prelude.*</code> and any aliases for this name are <em>extended</em> to work for the new type. For matrices, this would look like, for example,</p> <pre><code>instance Num Matrix where m * n = {- implementation goes here -} </code></pre></li> <li><p>We may define a different name than <code>*</code>.</p> <pre><code>m |*| n = {- implementation goes here -} </code></pre></li> <li><p>We may define the name <code>*</code>. Whether this name is defined as part of a new type class or not is immaterial. If we do nothing else, there will then be at least two definitions of <code>*</code>, namely, the one in the current module and the one implicitly imported from the <code>Prelude</code>. We have a variety of ways of dealing with this. The simplest is to explicitly import the <code>Prelude</code>, and ask for the name <code>*</code> not to be defined:</p> <pre><code>import Prelude hiding ((*)) </code></pre> <p>You might alternately choose to leave the implicit import of <code>Prelude</code>, and use a qualified <code>*</code> everywhere you use it. Other solutions are also possible.</p></li> </ul> <p>The main point I want you to take away from this is: <em>the name <code>*</code> is in no way special</em>. It is just a name defined by the <code>Prelude</code>, and all of the tools we have available for namespace control are available.</p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    2. VO
      singulars
      1. This table or related slice is empty.
    3. VO
      singulars
      1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload