Communication between actions in Applicative style

Rodrigo

Haskell design patterns, writes this example:

(+) <$> Nothing <*> Just 10 <*> Just 20

to justify that there is limited communication between actions in Applicative style.

The problem is I do not get this example to compile in ghci, with error:

<interactive>:28:1: error:
    • Non type-variable argument in the constraint: Num (a -> b)
      (Use FlexibleContexts to permit this)
    • When checking the inferred type
        it :: forall a b. (Num (a -> b), Num a) => Maybe b
leftaroundabout

The example is wrong. Any of these work:

Prelude> (+) <$> Nothing <*> Just 10
Nothing
Prelude> (+) <$> Just 10 <*> Just 20
Just 30
Prelude> (+) <$> Just 20 <*> Nothing
Nothing

but the one given doesn't, because (+) has only two arguments.

Using it as (+)<$>_<*>_<*>_ means the compiler tries to infer a type in which (+) has three arguments. Well, that's not completely inconceivable since Haskell multi-argument functions really are functions of an argument yielding a function of another argument yielding...
So, a “two-argument function” a -> a -> a can in principle have more arguments if you instantiate a itself with a function type. Say, a ~ (Int -> Int), then

(+) :: Num (Int -> Int) => (Int -> Int) -> (Int -> Int) -> Int -> Int
                           ┗━━━━━━━━━━┛    ┗━━━━━━━━━━┛    ┗━┛

Voilà, three arguments. The problem is that Int -> Int or more generally a->b is not a numerical type, i.e. Num (a -> b) is not a constraint that can be fulfilled, though somebody conceivable could write such an instance.

Note that sometimes, constraints as Monoid (a,b) can make sense, and GHC does allow them, but you'll need to follow the advice and enable the FlexibleContexts extension by either putting {-# LANGUAGE FlexibleContexts #-} on top of your source file, or :set -XFlexibleContexts in GHCi. In your example, that doesn't help at all though.

To apply (+) to an arbitrary number or arguments, you can fold it over a list:

> :m +Data.List
> foldl1 (+) [0,10,20]
30

Likewise, you can fold the applicative-lifted form (liftA2 (+) p q ≡ (+)<$>p<*>q) over a list of Maybe-numbers:

> :m +Control.Applicative
> foldl1 (liftA2(+)) [Nothing, Just 10, Just 20]
Nothing
> foldl1 (liftA2(+)) [Just 0, Just 10, Just 20]
Just 30

Collected from the Internet

Please contact [email protected] to delete if infringement.

edited at
0

Comments

0 comments
Login to comment

Related