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 Applicatives 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 <|> emptyLet'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.
