Reputation: 361
I'm trying to go through the Applicative example from Learn You a Haskell for Great Good! book.
my code is here:
class (Functor f) => Applicative f where
pure :: a -> f a
(<*>) :: f (a -> b) -> f a -> f b
instance Applicative Maybe where
pure = Just
Nothing <*> _ = Nothing
(Just f) <*> something = fmap f something
main = do
print $ Just (+3) <*> Just 9
print $ pure (+3) <*> Just 10
print $ pure (+3) <*> Just 9
print $ Just (++"hahah") <*> Nothing
print $ Nothing <*> Just "woot"
and I got this error message:
No instance for (Show b0) arising from a use of `print'
The type variable `b0' is ambiguous
Possible fix: add a type signature that fixes these type variable(s)
Note: there are several potential instances:
instance Show Double -- Defined in `GHC.Float'
instance Show Float -- Defined in `GHC.Float'
instance (Integral a, Show a) => Show (GHC.Real.Ratio a)
-- Defined in `GHC.Real'
...plus 23 others
In the expression: print
In a stmt of a 'do' block: print $ Nothing <*> Just "woot"
In the expression:
do { print $ Just (+ 3) <*> Just 9;
print $ pure (+ 3) <*> Just 10;
print $ pure (+ 3) <*> Just 9;
print $ Just (++ "hahah") <*> Nothing;
.... }
Why does it fail and how can I fix this?
Upvotes: 0
Views: 277
Reputation: 2223
The problem lies in the last print
line. Basically, you are applying a function String -> b
by using <*>
. It just so happens that you use Nothing
to wrap the function, so there is no function in the end. The result of the application is some Maybe b
where b
is arbitrary, but only those a
s that are instances of Show
produce instances for Maybe a
. But remember you have an arbitrary b
, which need not be an instance of Show
. The print
however requires its argument to be an instance of Show
. Since you cannot prove b
to be instance of Show
neither can you prove Maybe b
to be an instance of Show
, thus print
does not apply to the value of type Maybe b
.
To make it go away you must specify what exact type of function you meant to be contained. So that the result has some known type:
(Nothing :: Maybe (String -> Int)) <*> ...
or you could just provide the type for the whole expression that is passed as input of the print
:
print (... :: Maybe Int)
Upvotes: 3