Note that there are some explanatory texts on larger screens.

plurals
  1. POFunctor/Applicative-like typeclass for composing (a->a) functions instead of (a->b)?
    primarykey
    data
    text
    <p>I have a type that looks like this:</p> <pre><code>newtype Canonical Int = Canonical Int </code></pre> <p>and a function</p> <pre><code>canonicalize :: Int -&gt; Canonical Int canonicalize = Canonical . (`mod` 10) -- or whatever </code></pre> <p>(The Canonical type may not be important, it just serves to distinguish "raw" values from "canonicalized" values.)</p> <p>I'd like to create some machinery so that I can canonicalize the results of function applications.</p> <p>For example: <strong>(Edit: fixed bogus definitions)</strong></p> <pre><code>cmap :: (b-&gt;Int) -&gt; (Canonical b) -&gt; (Canonical Int) cmap f (Canonical x) = canonicalize $ f x cmap2 :: (b-&gt;c-&gt;Int) -&gt; (Canonical b) -&gt; (Canonical c) -&gt; (Canonical Int) cmap2 f (Canonical x) (Canonical y) = canonicalize $ f x y </code></pre> <p>That's superficially similar to Functor and Applicative, but it isn't quite, because it's too specialized: I can't actually compose functions (as required by the homomorphism laws for Functor/Applicative) unless 'b' is Int.</p> <p>My goal is to use existing library functions/combinators, instead of writing my own variants like <code>cmap</code>, <code>cmap2</code>. Is that possible? Is there a different typeclass, or a different way to structure Canonical type, to enable my goal?</p> <p>I've tried other structures, like </p> <pre><code>newtype Canonical a = Canonical { value :: a, canonicalizer :: a -&gt; a } </code></pre> <p>but that hits the same non-composability problem, because I can't translate one canonicalizer to another (I just want to use the canonicalizer of the result type, which is always <code>Int</code> (or <code>Integral a</code>)</p> <p>And I can't force "specialization-only" like so, this isn't valid Haskell:</p> <pre><code>instance (Functor Int) (Canonical Int) </code></pre> <p>(and similar variations)</p> <p>I also tried</p> <pre><code>newtype (Integral a) =&gt; Canonical a = Canonical a -- -XDatatypeContexts instance (Integral a) =&gt; Functor Canonical where fmap f (Canonical x) = canonicalize $ f x </code></pre> <p>but GHC says that <code>DatatypeContexts</code> is deprecated, and a bad idea, and more severely, I get:</p> <pre><code> `Could not deduce (Integral a1) arising from a use of 'C' from the context (Integral a) bound by the instance declaration [...] fmap :: (a1 -&gt; b) -&gt; (C a1 -&gt; C b) </code></pre> <p>which I think is saying that the constraint <code>Integral a</code> can't actually be used to constrain <code>fmap</code> to <code>(Integral -&gt; Integral)</code> the way I wish, which is sort of obvious (since <code>fmap</code> has two type variables) :-(</p> <p>And of course this isn't valid Haskell either</p> <pre><code>instance (Integer a) =&gt; Functor Canonical where </code></pre> <p><strong>Is there a similar typeclass I could use, or am I wrong to try to use a typeclass at all for this functionality of "implicitly canonicalize the results of function calls"?</strong></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.
 

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