So let's say I want to define a newtype that houses a function:
newtype Test m a = Test(m -> (a, m))
This could be used to house state of some sort.
Now let's say I would like to implement fmap for this newtype.
instance Functor (Test m) where
--fmap :: (a -> b) -> Test m a -> Test m a -> b
fmap f (Test f1) (Test f2) = ?
Since the newtype houses functions there's no way to use pattern matching to break f1 and f2 apart.
For instance I initially thought maybe I could pass the input value of f2 into the call f1 to yield a (a, m) tuple, but I don't think you can do that.
ie
tup = f1 (get input of f2)
Is anyone able to provide me with what concepts I'm missing to deal with this scenario or is this just not possible?
Thanks
UPDATE
Big thanks to Redu and Willem Van Onsem.
Looks like I was lacking in understanding of how to use the composition operator (.).
Basically the key here is use (.) to grab the first element of the tuple and then do a bunch of partial function definitions to get into the state needed by fmap. Here is my fmap implementation without using the library function. Purposefully verbose to help with understanding.
alterParamStateHelper :: (a -> b) -> (m -> a) -> m -> (b, m)
alterParamStateHelper f1 f2 m = (b, m)
where
a = f2 e
b = f1 a
alterParamState :: (a -> b) -> (m -> (a, m)) -> (m -> (b, m))
alterParamState f1 f2 = alterParamStateHelper f1 h1
where
h1 = fst . f2--m -> a
instance Functor (Test m) where
-- fmap :: (a -> b) -> Test m a -> Test m b
fmap f1 (Test f2) = Test (alterParamState f1 f2)
Since the newtype houses functions there's no way to use pattern matching to break
f1
andf2
apart.
There is a problem with your fmap
signature here. fmap
has signature fmap :: Functor f => (a -> b) -> f a -> f b
so if f ~ Test m
, then the signature is fmap :: (a -> b) -> Test m a -> Test m b
.
We thus can here define an fmap
where we "post-process" the result of the function. We thus construct a new function that will use the old function to construct a 2-tuple (a, m)
, and then call f
on the first item, such that we construct a tuple (b, m)
:
import Control.Arrow(first)
instance Functor (Test m) where
fmap f (Test g) = Test (first f . g)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With