Reputation: 99
I'm trying to design a type that holds some value and keeps track of all operations done upon it. It does this by storing them in string format (this is not for a project, just learning)
I tried to make it a Functor
like this:
data WithLogs a = WithLogs {value :: a, logs :: [String]}
instance Functor WithLogs where
fmap :: (a -> b) -> WithLogs a -> WithLogs b
fmap f WithLogs {value, logs} =
let newValue = f value
newLogs = logs ++ [show value ++ " -> " ++ show newValue]
in WithLogs {value = newValue, logs = newLogs}
This gives me an error at the line "newLogs = logs ++ [show value ++ " -> " ++ show newValue]
", saying "No instance for (Show a) arising from a use of ‘show’"
. I then add the required contraints to make sure that both a
and b
can be show
n
instance Functor WithLogs where
fmap :: (Show a, Show b) => (a -> b) -> WithLogs a -> WithLogs b
fmap f WithLogs {value, logs} =
let newValue = f value
newLogs = logs ++ [show value ++ " -> " ++ show newValue]
in WithLogs {value = newValue, logs = newLogs}
This then gives me the error "No instance for (Show a) arising from the check that an instance signature is more general than the type of the method (instantiated for this instance)
"
I think okay, so I need to constrain the instance, leading to this code:
instance (Show a) => Functor WithLogs where
fmap :: (Show a, Show b) => (a -> b) -> WithLogs a -> WithLogs b
fmap f WithLogs {value, logs} =
let newValue = f value
newLogs = logs ++ [show value ++ " -> " ++ show newValue]
in WithLogs {value = newValue, logs = newLogs}
This hits me with two* errors, the first being that the (Show a)
in the instance declaration cannot be deduced, and its right, how could it? I can't pass a
to Functor (WithLogs a)
because Functor
expects a (Type -> Type)
, but I somehow need to constrain fmap
so that I can use show
on the contained value. I need a way to tell WithLogs
that it can only take show
able types to be an instance of Functor
. Is there a way to do this?
*: in case it's any help, the other error is "Could not deduce (Show b) arising from the check that an instance signature is more general than the type of the method (instantiated for this instance)
"
Upvotes: 1
Views: 44