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
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.
Comments