Exploring alternatives
Today I'm going to play with Alternatives.
(spoiler: I failed to understand what some
and many
do, and I guess that would be an essential part of getting Alternative
. So there's not much thing useful in this article.)
Just as my other type-tetris attempts, this is not a tutorial about Alternative
, I'll just provide some examples and intuitions gained throughout playing with it.
I happened to heard this typeclass by a quick scan on typeclassopedia, and there are only few functions related to it, which I think might not take much time to try them all. These are all motivations about this article.
As always, bold sentences stands for my intuitions.
“a monoid on applicative functors”
Alternative
is a typeclass lied in Control.Applicative
, most of the time, I import this package to use functions like <$>
, <*>
and data type ZipList
, but no more. I happened to heard this typeclass by a quick scan on typeclassopedia, and there are only few functions related to it, which I think might not take much time to try them all. These are all motivations about this article.
First function in this class is called empty
, so I guess Alternative
is some typeclass that allows containing nothing. This would explain why there are so many Applicative
s but I can only see []
and Maybe
being instances of this typeclass.
The document says Alternative
is “a monoid on applicative functors”. So we can make an analogy between (mempty, mappend)
from Monoid
and (empty, <|>)
from Alternative
. Let's try it out:
v1 :: [String]
v1 = empty <|> empty <|> empty
v2 :: [String]
v2 = v1 <|> pure "foo" <|> pure "bar"
v3 :: Maybe Int
v3 = pure 10 <|> pure 20
v4 :: Maybe Char
v4 = empty <|> pure 'A' <|> undefined
v5 :: Maybe ()
v5 = empty <|> empty <|> empty
Let's bring up GHCi:
empty
works like what we expected, and <|>
for lists seems straightforward. But when it comes to Maybe
, we find that only the first non-Nothing
one takes effect, if any.
some
and many
The type for some
and many
are identical, so just fill in some instances I come up with on the fly:
But when I try this out on GHCi, something is going wrong:
I gave v6
some time to run but it didn't terminate, so I cancelled it by hand.
By looking at the document, I find some clue: some
and many
seem to look for some solutions to the following equations:
some v = (:) <$> v <*> many v
many v = some v <|> pure []
-- rewrite to break the recursive relation will help?
some v = (:) <$> v <*> (some v <|> pure [])
many v = ((:) ($) v <*> many v) <|> pure []
I can't go any further from here, but doing some research, I find the following links that might help, but for now I just leave this two functions as mysteries. (Maybe it's just something like fix
, interesting, but IMHO not useful ).
Related links:
optional
For the rest of the story, I'll just type them directly into GHCi.
The last function about Alternative
is optional
, Let's check its type and feed it with some instances:
λ> :t optional
optional :: Alternative f => f a -> f (Maybe a)
λ> optional Nothing
Just Nothing
λ> optional $ Just 1
Just (Just 1)
λ> optional []
[Nothing]
λ> optional [1,2,3]
[Just 1,Just 2,Just 3,Nothing]
Wait a minute, is f a -> f (Maybe a)
looks familiar to you? It looks like an unary function that has type a -> Maybe a
under some contexts. I think the simplest expression that matches this type would be (Just <$>)
. Let's do the same thing on it.
λ> :t (Just <$>)
(Just <$>) :: Functor f => f a -> f (Maybe a)
λ> (Just <$>) Nothing
Nothing
λ> (Just <$>) Just 1
Just (Just 1)
λ> (Just <$>) []
[]
λ> (Just <$>) [1,2,3]
[Just 1,Just 2,Just 3]
Comparing the output of optional
and (Just <$>)
, we find that optional
will attach an empty
to the end of this monoid. And that empty
would be the “none” part from optional
's description: “One or none”. In addition, we've seen <|>
is the binary operation for this monoid, so we can have a guess:
optional v = (Just <$> v) <|> pure Nothing
And this turns out to be the exact implementation.
Summary
Not much is done in this post, I have to admit that type-tetris is not always the best way. As an afterthought, I didn't know how Alternative
will be used so there was little hint that I can rely on when I was trying to figure out many
and some
.
Anyway, if happened to read all contents in this article, sorry for wasting your time and thanks for your patience.