<div dir="ltr">Hilco, <div><br></div><div>I am going to use a lot of Haskell concepts here, but I am a strong believer that using the correct terms empowers the learner to go out and continue their education on their own. </div><div><br></div><div><u>Your first question is <b>is it possible to define Result as Result success failure and still create an instance of Functor</b>?</u></div><div><br></div><div>The answer to that is <b>yes</b>. We can look up the definition of the <b>Functor typeclass</b> (use <i>:i Functor</i> in GHCI), and we can see the following: <b>class Functor (f :: * -> *) where</b>.... </div><div><br></div><div>>From that definition, we can see that we can have an instance of Functor for any type that has the <i>kind * -> *</i>. It seems like you are familiar with treating type constructors as functions at the type level, so what we are saying here is that in order for a type constructor to be a functor, it <u>has</u> to be a type constructor that takes <u>one</u> type constant to yield another type constant. Your type <b>Result</b> has the kind <b>* -> * -> *</b>. It takes two type constants, so we know that wont "fit" into Functor, and we have to partially apply the <b>Result</b> type constructor to get another type constructor with the kind <b>* -> *</b>, which can have an instance of Functor. </div><div><br></div><div>What I think is missing from your understanding is this - if you change your data declaration to be <b>Result success failure</b>, then your instance of functor will only be able to modify the failure case. Why? Because when you write your instance of functor, it will look like this: <b>instance Functor (Result success) where...</b>. If we look at the signature of <b>fmap :: (a -> b) -> f a -> f b</b>, and then we specialize so that <b>f ~ Result success</b>, we get <b>fmap :: (a -> b) -> Result success a -> Result success b</b>. In other words, you have already baked in the first type argument to <b>Result</b> when you are writing your instance of Functor for it, and are not allowed to change it anymore. </div><div><br></div><div><u>Your second question <b><span style="color:rgb(0,0,0);font-family:arial,sans-serif;font-size:12.8px;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;background-color:rgb(255,255,255);float:none;display:inline">I would like to be able to </span><span style="color:rgb(0,0,0);font-family:arial,sans-serif;font-size:12.8px;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;background-color:rgb(255,255,255);float:none;display:inline">express that "result" is not touched...</span></b></u></div><div><b><span style="color:rgb(0,0,0);font-family:arial,sans-serif;font-size:12.8px;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;background-color:rgb(255,255,255);float:none;display:inline"><br></span></b></div><div><span style="color:rgb(0,0,0);font-family:arial,sans-serif;font-size:12.8px;font-variant-ligatures:normal;font-variant-caps:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;background-color:rgb(255,255,255);float:none;display:inline">I am assuming here that you are talking about this piece of code "<span style="color:rgb(80,0,80);font-family:arial,sans-serif;font-size:12.8px;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-weight:400;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;background-color:rgb(255,255,255);text-decoration-style:initial;text-decoration-color:initial;float:none;display:inline">fmap _ result@(Failure error) = result" using your original functor instance and data Result failure success...</span></span></div><div><span style="color:rgb(0,0,0);font-family:arial,sans-serif;font-size:12.8px;font-variant-ligatures:normal;font-variant-caps:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;background-color:rgb(255,255,255);float:none;display:inline"><span style="color:rgb(80,0,80);font-family:arial,sans-serif;font-size:12.8px;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-weight:400;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;background-color:rgb(255,255,255);text-decoration-style:initial;text-decoration-color:initial;float:none;display:inline"><br></span></span></div><div><span style="color:rgb(0,0,0);font-family:arial,sans-serif;font-size:12.8px;font-variant-ligatures:normal;font-variant-caps:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;background-color:rgb(255,255,255);float:none;display:inline">We can't express that result is not touched. Why? Because result <u style="font-style:normal">is</u> touched. It has to be. As you yourself mentioned, on the left-hand side we have a value of one type, and on the right-hand side we have a value of a different type. Even though we don't witness the change at the value level, we do have a change at the type level. So we can't express it because it is not what is happening. Now, I get what you are saying - the result on the left-hand side has the same data as the right-hand side, same data constructor, etc, but it is still not the same value.</span></div><div><span style="color:rgb(0,0,0);font-family:arial,sans-serif;font-size:12.8px;font-variant-ligatures:normal;font-variant-caps:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;background-color:rgb(255,255,255);float:none;display:inline"><br></span></div><div><span style="color:rgb(0,0,0);font-family:arial,sans-serif;font-size:12.8px;font-variant-ligatures:normal;font-variant-caps:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;background-color:rgb(255,255,255);float:none;display:inline">On your third question, regarding GHC being smart enough to realize a NOP, I don't know. </span></div><div><span style="color:rgb(0,0,0);font-family:arial,sans-serif;font-size:12.8px;font-variant-ligatures:normal;font-variant-caps:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;background-color:rgb(255,255,255);float:none;display:inline"><br></span></div><div><span style="color:rgb(0,0,0);font-family:arial,sans-serif;font-size:12.8px;font-variant-ligatures:normal;font-variant-caps:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;background-color:rgb(255,255,255);float:none;display:inline">I hope this helps! </span></div></div><div class="gmail_extra"><br><div class="gmail_quote">On Sat, Mar 3, 2018 at 2:32 PM, Hilco Wijbenga <span dir="ltr"><<a href="mailto:hilco.wijbenga@gmail.com" target="_blank">hilco.wijbenga@gmail.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Hi all,<br>
<br>
I'm trying to implement my own Result type (and yes, I'm aware you can<br>
abuse Either for this :-) ) but doing something as (seemingly?) simple<br>
as implementing a Functor instance was surprisingly difficult.<br>
<br>
data Result failure success<br>
    = Success success<br>
    | Failure failure<br>
<br>
instance Functor (Result failure) where<br>
    fmap f (Success value) = Success (f value)<br>
    fmap _ (Failure error) = Failure error<br>
    -- fmap _ result@(Failure error) = result<br>
    -- fmap _ result          = result<br>
<br>
1) Is it possible to define "Result" as "Result success failure"<br>
(instead of "Result failure success") and _still_ create an instance<br>
of Functor?<br>
2) The two alternatives for fmap for the Failure scenario do not<br>
compile (the end result is "Result failure a" instead of "Result<br>
failure b") and that makes sense. But I would like to be able to<br>
express that "result" is not touched. Is there any way to do that?<br>
3) And while wondering about that, is GHC smart enough to realize that<br>
"= Failure error" in the failure scenario is actually a NOP? (I'm just<br>
curious.)<br>
<br>
Cheers,<br>
Hilco<br>
______________________________<wbr>_________________<br>
Beginners mailing list<br>
<a href="mailto:Beginners@haskell.org">Beginners@haskell.org</a><br>
<a href="http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners" rel="noreferrer" target="_blank">http://mail.haskell.org/cgi-<wbr>bin/mailman/listinfo/beginners</a><br>
</blockquote></div><br><br clear="all"><div><br></div>-- <br><div class="gmail_signature" data-smartmail="gmail_signature">Steven Leiva<br>305.528.6038<br><a href="mailto:leiva.steven@gmail.com" target="_blank">leiva.steven@gmail.com</a><br><a href="http://www.linkedin.com/in/stevenleiva" target="_blank">http://www.linkedin.com/in/stevenleiva</a><br></div>
</div>