Home > Back-end >  Applicative implementation in Haskell
Applicative implementation in Haskell

Time:10-18

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)
  • Related