I'm new to Haskell, learning Functor, Applicative, and Monad.
I checked the Functor instance for Either type from hackage is:
data Either a b = Left a | Right b
instance Functor (Either a) where
fmap _ (Left x) = Left x
fmap f (Right y) = Right (f y)
and I am asked to do the Functor, Applicative, Monad instance for extended Either called MyEither:
data MyEither a b = MyLeft a | MyRight b | Nothing
deriving (Eq, Show)
My question is:
1 How to extend Nothing in my instance?
2 Does deriving have to be written in the instance?
Can anyone get me some tips?
CodePudding user response:
When you implement the instance you don't need to write deriving
. deriving
is for when you let the compiler derive an instance for you when you are defining a new type.
For Nothing
, pattern match on it and return Nothing
for the implementation of all of FAM
. There isn't much you can do with it.
Here is a similar example that may help you.
data Nope a = NopeDataJpg deriving (Eq, Show)
instance Functor Nope where
fmap _ _ = NopeDataJpg
instance Applicative Nope where
pure x = NopeDataJpg
_ <*> _ = NopeDataJpg
instance Monad Nope where
return = pure
_ >>= _ = NopeDataJpg
Also, here are the Functor
, Applicative
, and Monad
implementations of Maybe
in GHC. How they handle Nothing
is pretty similar to what you need to do for your data type.
CodePudding user response:
When you write down your instances, start by writing out the types explicitly:
data MyEither a b = MyLeft a | MyRight b | MyNothing
deriving (Eq, Show)
instance Functor (MyEither a) where
-- fmap :: Functor f => (b -> c) -> f b -> f c
-- fmap :: (b -> c) -> MyEither a b -> MyEither a c
(I'll use MyNothing
here to prevent any mix-ups with the Maybe
's Nothing
).
And now we are ready to enumerate all possibilities according to the data type definition:
fmap bc (MyLeft aValue) = result where
-- bc :: b -> c
-- MyLeft aValue :: MyEither a b
-- result :: MyEither a c
.....
here we must produce a value of type MyEither a c
as the result. The function bc
is useless here, as we only have access to the value aValue :: a
of type a
:
MyLeft aValue :: MyEither a b
--------------------------------
aValue :: a
Thus we have two possibilities here:
result = MyLeft aValue
which will construct a new value, this time of typeMyEither a c
as determined by the type signature; orresult = ...
.
Fill the dots, and make the choice between 1. and 2, completing the definition of this clause, fmap bc (MyLeft aValue) = ...
.
The next possibility is
fmap bc (MyRight bValue) = ...
This time we do have an access to a value of type b
, so the function bc
can come quite handy, since
bValue :: b
bc :: b -> c
-------------------------
bc bValue :: c
and
cValue :: c
--------------------------------
myRight cValue :: MyEither a c
Thus the natural definition for that clause is
fmap bc (MyRight bValue) = MyRight cValue
where
cValue = ....
although of course the same second option is also technically possible as was in the first clause. What's certainly impossible is to use MyLeft
to construct a MyEither a c
value here, as we have absolutely no access to any a
type value at all here.... except undefined
.
And now there's only one more possibility left, for a value of type MyEither a b
that our fmap
must handle, according to it type signature (remember, fmap :: (b -> c) -> MyEither a b -> MyEither a c
). An that value is ...
fmap bc MyNothing =
Again, we must produce a value of type MyEither a c
as the result. This time we have no access to any value of type neither b
nor a
. So there is no other choice other than return ...
.......
(sans the uses of undefined
of course). Do complete the definition.
And I hope you are now able to finish up the other definitions as needed.