Reputation: 34099
I have following type definition:
data Hello a b = Hi a
| Sali b
deriving (Show, Eq)
and it isn't an instance of Applicative
but I can still use pure
to convert it to Applicative
why?
*ExercisesTraversable Data.Monoid Control.Applicative> :t pure $ Hi 34
pure $ Hi 34 :: (Num a, Applicative f) => f (Hello a b)
*ExercisesTraversable Data.Monoid Control.Applicative> pure $ Hi 34
Hi 34
And when I try:
*ExercisesTraversable Data.Monoid Control.Applicative> (Sali (*2)) <*> (Sali 4)
<interactive>:23:1: error:
* Non type-variable argument
in the constraint: Applicative (Hello a)
(Use FlexibleContexts to permit this)
* When checking the inferred type
it :: forall b a. (Num b, Applicative (Hello a)) => Hello a b
that is clear, because it isn't an Applicative
instance.
Upvotes: 1
Views: 106
Reputation: 532153
Since you aren't specifying any Applicative
type in particular, ghci
is defaulting to IO
, i.e. pure $ Hi 34
returns a value of type Num a => IO (Hello a b)
. That is, Hello a b
isn't the f
in a -> f a
, it's the a
.
You can see more explicitly that Hello a b
is the typed wrapped by an arbitrary Applicative
by specifying various Applicative
functors for the value:
Prelude> (pure $ Hi 34) :: Either String (Hello Int b)
Right (Hi 34)
Prelude> (pure $ Hi 34) :: Maybe (Hello Int b)
Just (Hi 34)
Prelude> (pure $ Hi 34) :: [Hello Int b]
[Hi 34]
Upvotes: 6
Reputation: 34411
When you call pure x
it is not x
that should be Applicative
, but the whole pure x
expression. Take a look at pure
type:
Prelude> :t pure
pure :: Applicative f => a -> f a
See? You pass it a
, but Applicative
constraint is on f
, and that f
only appears in the result. So, it is the result that should be of class Applicative
, and as @chepner said, GHCi prompt defaults to IO
, which is Applicative
.
Upvotes: 4