Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>The dual of a monoid is a comonoid. Recall that a monoid is defined as (something isomorphic to)</p> <pre><code> class Monoid m where create :: () -&gt; m combine :: (m,m) -&gt; m </code></pre> <p>with these laws</p> <pre><code> combine (create (),x) = x combine (x,create ()) = x combine (combine (x,y),z) = combine (x,combine (y,z)) </code></pre> <p>thus </p> <pre><code> class Comonoid m where delete :: m -&gt; () split :: m -&gt; (m,m) </code></pre> <p>some standard operations are needed</p> <pre><code> first :: (a -&gt; b) -&gt; (a,c) -&gt; (b,c) second :: (c -&gt; d) -&gt; (a,c) -&gt; (a,d) idL :: ((),x) -&gt; x idR :: (x,()) -&gt; x assoc :: ((x,y),z) -&gt; (x,(y,z)) </code></pre> <p>with laws like</p> <pre><code>idL $ first delete $ (split x) = x idR $ second delete $ (split x) = x assoc $ first split (split x) = second split (split x) </code></pre> <p>This typeclass looks weird for a reason. It has an instance</p> <pre><code>instance Comonoid m where split x = (x,x) delete x = () </code></pre> <p>in Haskell, this is the <em>only</em> instance. We can recast reader as the exact dual of writer, but since there is only one instance for comonoid, we get something isomorphic to the standard reader type.</p> <p>Having all types be comonoids is what makes the category "Cartesian" in "Cartesian Closed Category." "Monoidal Closed Categories" are like CCCs but without this property, and are related to substructural type systems. Part of the appeal of linear logic is the increased symmetry that this is an example of. While, having substructural types allows you to define comonoids with more interesting properties (supporting things like resource management). In fact, this provides a framework for understand the role of copy constructors and destructors in C++ (although C++ does not enforce the important properties because of the existence of pointers).</p> <p>EDIT: Reader from comonoids</p> <pre><code>newtype Reader r x = Reader {runReader :: r -&gt; x} forget :: Comonoid m =&gt; (m,a) -&gt; a forget = idL . first delete instance Comonoid r =&gt; Monad (Reader r) where return x = Reader $ \r -&gt; forget (r,x) m &gt;&gt;= f = \r -&gt; let (r1,r2) = split r in runReader (f (runReader m r1)) r2 ask :: Comonoid r =&gt; Reader r r ask = Reader id </code></pre> <p>note that in the above code every variable is used exactly once after binding (so these would all type with linear types). The monad law proofs are trivial, and only require the comonoid laws to work. Hence, <code>Reader</code> really is dual to <code>Writer</code>.</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