[Haskell-beginners] Functor instance

Steven Leiva leiva.steven at gmail.com
Mon Mar 5 15:38:22 UTC 2018


Hilco,

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.

*Your first question is is it possible to define Result as Result success
failure and still create an instance of Functor?*

The answer to that is *yes*. We can look up the definition of the *Functor
typeclass* (use *:i Functor* in GHCI), and we can see the following: *class
Functor (f :: * -> *) where*....

>From that definition, we can see that we can have an instance of Functor
for any type that has the *kind * -> **. 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
*has* to be a type constructor that takes *one* type constant to yield
another type constant. Your type *Result* has the kind ** -> * -> **. It
takes two type constants, so we know that wont "fit" into Functor, and we
have to partially apply the *Result* type constructor to get another type
constructor with the kind ** -> **, which can have an instance of Functor.

What I think is missing from your understanding is this - if you change
your data declaration to be *Result success failure*, 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: *instance Functor
(Result success) where...*. If we look at the signature of *fmap :: (a ->
b) -> f a -> f b*, and then we specialize so that *f ~ Result success*, we
get *fmap :: (a -> b) -> Result success a -> Result success b*. In other
words, you have already baked in the first type argument to *Result* when
you are writing your instance of Functor for it, and are not allowed to
change it anymore.

*Your second question I would like to be able to express that "result" is
not touched...*

I am assuming here that you are talking about this piece of code "fmap _
result@(Failure error) = result" using your original functor instance and
data Result failure success...

We can't express that result is not touched. Why? Because result *is* 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.

On your third question, regarding GHC being smart enough to realize a NOP,
I don't know.

I hope this helps!

On Sat, Mar 3, 2018 at 2:32 PM, Hilco Wijbenga <hilco.wijbenga at gmail.com>
wrote:

> Hi all,
>
> I'm trying to implement my own Result type (and yes, I'm aware you can
> abuse Either for this :-) ) but doing something as (seemingly?) simple
> as implementing a Functor instance was surprisingly difficult.
>
> data Result failure success
>     = Success success
>     | Failure failure
>
> instance Functor (Result failure) where
>     fmap f (Success value) = Success (f value)
>     fmap _ (Failure error) = Failure error
>     -- fmap _ result@(Failure error) = result
>     -- fmap _ result          = result
>
> 1) Is it possible to define "Result" as "Result success failure"
> (instead of "Result failure success") and _still_ create an instance
> of Functor?
> 2) The two alternatives for fmap for the Failure scenario do not
> compile (the end result is "Result failure a" instead of "Result
> failure b") and that makes sense. But I would like to be able to
> express that "result" is not touched. Is there any way to do that?
> 3) And while wondering about that, is GHC smart enough to realize that
> "= Failure error" in the failure scenario is actually a NOP? (I'm just
> curious.)
>
> Cheers,
> Hilco
> _______________________________________________
> Beginners mailing list
> Beginners at haskell.org
> http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners
>



-- 
Steven Leiva
305.528.6038
leiva.steven at gmail.com
http://www.linkedin.com/in/stevenleiva
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.haskell.org/pipermail/beginners/attachments/20180305/b92380c8/attachment.html>


More information about the Beginners mailing list