Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p>You could possibly use type classes to make a function behave as both <code>Point -&gt; Point -&gt; Rectangle</code> and <code>Float -&gt; Float -&gt; Float -&gt; Float -&gt; Rectangle</code>, but I wouldn't advocate it. It will be to much trouble for the gain. I don't think there's anyway you could make such an overloaded name usable in pattern matching anyway.</p> <p>The way I see it, if you're only ever going to be using <code>Point</code> values by deconstructing them and operating on the raw <code>Float</code> values, then you're not really getting that much out of it, so you could resolve your problem by getting rid of it entirely.</p> <p>But you're missing a golden opportunity to implement a function to adjust a point directly! </p> <p>For starters I would make an <code>Offset</code> type to hold your <code>a</code> and <code>b</code> values. Then you make a function <code>adjust :: Offset -&gt; Point -&gt; Point</code> to do the combining. And then your <code>nudge</code> doesn't even need to understand the internal structure of a <code>Point</code> to do its job!</p> <p>For example (Disclaimer: I haven't actually compiled this)<sup>1</sup>:</p> <pre><code>data Point = Point Float Float deriving (Show) data Offset = Offset Float Float deriving (Show) data Shape = Circle Point Float | Rectangle Point Point deriving (Show) adjust :: Point -&gt; Offset -&gt; Point adjust (Point x y) (Offset ox oy) = Point (x + ox) (y + oy) nudge :: Shape -&gt; Offset -&gt; Shape nudge (Circle c r) o = Circle (adjust c o) r nudge (Rectangle p1 p2) o = Rectangle (adjust p1 o) (adjust p2 o) </code></pre> <p>And similarly there could be a whole family of operations on <code>Point</code> and <code>Offset</code>. For example <code>offsetFrom :: Point -&gt; Point -&gt; Offset</code> could be useful in your <code>surface</code> function. I once went overboard and used type classes to implement a family of operators (<code>|+|</code>, <code>|*|</code>, etc IIRC) which allowed various things to be combined (for example, you can add a <code>Point</code> and an <code>Offset</code> in either order to get a <code>Point</code>, you can add and subtract <code>Offset</code>s but not <code>Point</code>s, you can multiply <code>Offset</code>s by scalars but not <code>Point</code>s, etc). Not sure whether it was worth it in the end, but it made my code look like my maths a little more!</p> <p>With your current code you're effectively implementing all operations on <code>Point</code> again every time you need them (including the same adjustment operation twice in the same equation in <code>nudge</code>, which is my take on why it looks quite so bad).</p> <hr> <p><sup>1</sup> There's a certain argument to be made for making functions like <code>adjust</code> and <code>nudge</code> have signatures where the "main" thing being operated on comes last, so <code>adjust :: Offset -&gt; Point -&gt; Point</code> and <code>nudge :: Offset -&gt; Shape -&gt; Shape</code>. This can come in handy because then partially applying <code>adjust</code> gives you a "point transformer" with type <code>Point -&gt; Point</code>, and similarly you can partially apply <code>nudge</code> to get a "shape transformer" with type <code>Shape -&gt; Shape</code>.</p> <p>This helps when you have a collection of points or shapes and you want to apply the same transformation to all of them, for example:</p> <pre><code>data Shape = Polygon [Point] adjust :: Offset -&gt; Point -&gt; Point adjust (Offset ox oy) (Point x y) = Point (x + ox) (y + oy) nudge :: Offset -&gt; Shape -&gt; Shape nudge o (Polygon ps) = Polygon (map (adjust o) ps) </code></pre> <p>And generally "transformers" with type <code>Something -&gt; Something</code> are just useful things to have on your main data structures. So whenever you have a function that combines some auxiliary data with a <code>Something</code> to produce a new <code>Something</code>, it'll often turn out to be useful to put the <code>Something</code> as the last argument, so you have another easy source of transformer functions.</p>
 

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