3 ms·
You've made at least two comments now mentioning this idea of interchange, but there's more to all of this than just that. The Haskell standard libraries are fu
by Silhouette 7y ago
You've made at least two comments now mentioning this idea of interchange, but there's more to all of this than just that. The Haskell standard libraries are full of generic functions that can be applied to many practically useful types as long as those types provide certain basic guarantees.
For example, there is a useful little function
replicate :: Int -> a -> Seq a
that allows us to build a sequence of n of some value. But what if we don't have a raw value, but instead some Applicative wrapper around it, and instead of just getting a sequence of individually wrapped values, we want that Applicative structure around the sequence? That is, we want some function f that will give us
f 3 (Just 1) == Just (fromList [1, 1, 1])
but
f 3 Nothing == Nothing
with a Maybe, and
f 3 (Right 'x') == Right (fromList "xxx")
but
f 3 (Left "error message") == Left "error message"
with an Either, and similarly for any other Applicative.
Well, such a function also exists in Data.Sequence:
replicateA :: Applicative f => Int -> f a -> f (Seq a)
Because it works with any Applicative, it can just as well work out all of the possible outcomes when we roll three dice:
replicateA 3 [1, 2, 3, 4, 5, 6]
or repeat the action of any Monad three times:
replicateA 3 $ putStrLn "Hello, world!"
or repeat whatever behaviour some Applicative you haven't even written yet will have next week.
The rabbit hole gets as deep as you like. For example, we can easily compose a variety of other standard functions to count how many ways there are to reach each possible total in that dice example:
map (head &&& length) $ group $ sort $ fmap sum $ replicateA 3 [1, 2, 3, 4, 5, 6]
-- [(3,1),(4,3),(5,6),(6,10), ...]
Many of these functions have quite general types, for example sum working on any Foldable and fmap working on any Functor. Because a list is an Applicative and any Applicative is also a Functor, and since the individual results of the replicateA will be Seqs and any Seq is also a Foldable, everything works fine, and the list structure we started with is preserved all the way through.