I have a type show as below:
newtype WarningAccumulator w a = WarningAccumulator (a,[w])
deriving (Show,Eq)
And then I have a functor and applicative like below:
instance Functor (WarningAccumulator w) where
fmap :: (a -> b) -> WarningAccumulator w a -> WarningAccumulator w b
fmap f (WarningAccumulator (value, list)) = WarningAccumulator(f value, list)
instance Applicative (WarningAccumulator w) where
pure :: a -> WarningAccumulator w a
pure a = WarningAccumulator (a,[])
(<*>) :: WarningAccumulator w (a -> b) -> WarningAccumulator w a -> WarningAccumulator w b
(<*>) (WarningAccumulator (empty, f)) (WarningAccumulator (value, list)) =
WarningAccumulator (f value, list)
Now it gives me an error:
The function ‘f’ is applied to one value argument,
but its type ‘[w]’ has none
In the expression: f value
In the first argument of ‘WarningAccumulator’, namely
‘(f value, list)’
Which I do not understand. Can you explain this to me and then help me fix this issue?
CodePudding user response:
f
has the type [w]
, which is not the type of a function, so you cannot apply value
to it. You probably mean this instead:
-- (empty, f) changed to (f, empty)
(<*>) (WarningAccumulator (f, empty)) (WarningAccumulator (value, list)) =
WarningAccumulator (f value, list)
However, this instance of Applicative
is not lawful: it doesn’t satisfy the interchange law
u <*> pure y = pure ($ y) <*> u
For example:
u :: WarningAccumulator String (Int -> Int)
u = WarningAccumulator (( 1), ["warning"])
y :: Int
y = 2
u <*> pure y == WarningAccumulator (3, [])
whereas pure ($ y) <*> u == WarningAccumulator (3, ["warning"])
.
You probably want to concatenate the warnings instead of discarding what you’ve named empty
(which may not be empty):
(<*>) (WarningAccumulator (f, xs)) (WarningAccumulator (value, ys)) =
WarningAccumulator (f value, xs <> ys)