I recently saw a simple example that brought <*
and *>
to light.
validate :: String -> Maybe String
validate s = if s=="" then Nothing else Just s
>validate "a" *> validate "b"
Just "b"
>validate "" *> validate "b"
Nothing
>validate "a" <* validate "b"
Just "a"
>validate "a" <* validate ""
Nothing
>validate "a" <* validate "b" <* validate "c"
Just "a"
>validate "a" *> validate "b" <* validate "c"
Just "b"
This shows that the effects are important even if the values they produce are not.
My question is about the type signatures.
(*>) :: f a -> f b -> f b
(<*) :: f a -> f b -> f a
- Do these type signatures actually imply the behavior shown above?
I can see how one could reason "Obviously we have an Applicative - so that says something about behavior in general. For operator *>
, since we are throwing away the left value, the only possible meaning this function could have would be how the effect of the left hand side affects the entire operation."
In the case of Maybe
- then it seems that yes - the behavior is implied. For Either
, likewise the implication holds and the error would be propagated on an effect 'failure'.
Note I can only say the above because I now know how the implementation works, where my question pertains to the seasoned functional programmer who sees a signature like this the first time.
I have read where a type signature like [a] -> b :: Int
(probably not real code there) all but implies the implementation as the length of the list.
I have also searched for "implying implementation from type signature" and found that people have-been/are working on such things - but in general cannot be done (Uh - without that new GitHub thing :--)
So perhaps I have answered my own question but would appreciate any other answers or comments. I am still new to Haskell and after a number of false starts over the years, it is finally starting to sink in. And I have only scratched the surface...
Thanks