One of the examples from Learn You a Haskell is:
pure (+) <*> Just 3 <*> Just 5
He states:
So at first, we have
pure (+)
, which isJust (+)
I'm assuming that Haskell is using type inference on the <*>
function to determine that the pure
function on the LHS will be the one from the Maybe
instance of the Applicative
type class (based on the fact we're using Just 5
on the RHS, and Just
is a Maybe
).
However, is there ever a case where you have a value you'd like to turn into an Applicative Functor using the pure
method, but you aren't going to use it right away via the <*>
function and thus Haskell can't determine which pure
function to use? If so, how would you be explicit state which pure
function to use?
Or, is it the case that Haskell won't try to determine which pure
function until the result of the pure
function is used in some context (such as when you feed it to a <*>
function at some point)
What Is a Pure Function? In programming, a pure function is a function that has the following properties: The function always returns the same value for the same inputs. Evaluation of the function has no side effects.
Pure Function is a function (a block of code ) that always returns the same result if the same arguments are passed. It does not depend on any state, or data change during a program’s execution rather it only depends on its input arguments.
Evaluation of the function has no side effects. Side effects refer to changing other attributes of the program not contained within the function, such as changing global variable values or using I/O streams. Effectively, a pure function’s return value is based only on its inputs and has no other dependencies or effects on the overall program.
As pure functions always return the same output for the same input, we can cache the results of pure function calls. Caching refers to using a technique, such as memoization, to store the results of functions so that we only need to calculate them once.
You would give it a type annotation. If you were defining it as a variable, you would use a top-level type signature:
foo :: Maybe (Integer -> Integer -> Integer)
foo = pure (+)
(This also works in let
and where
clauses.)
Or if you were using it in an expression, you'd write (pure (+) :: Maybe (Integer -> Integer -> Integer))
.
You can also get the relevant pure
function without having to apply it to an argument. Since we have:
pure :: (Applicative f) => a -> f a
...we can say (pure :: a -> Maybe a)
to get a pure
of the desired type. But (pure :: a -> Maybe a) (+)
is more confusing than pure (+) :: Maybe (Integer -> Integer -> Integer)
, so the latter is probably more useful in general.
The last sentence of your question is correct, however: you can assign pure (+)
to a variable without a type signature, and use it later at a specific concrete type (such as Maybe (Integer -> Integer -> Integer)
) without having to use any type annotations at all. (There's a slight restriction: if you define it as a top-level variable without any type signature, then you can only use it as one specific type, not two in different places, due to the monomorphism restriction... but you probably don't need to worry about that.)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With