summaryrefslogtreecommitdiff
path: root/FunctorToMaybe.hs
diff options
context:
space:
mode:
Diffstat (limited to 'FunctorToMaybe.hs')
-rw-r--r--FunctorToMaybe.hs64
1 files changed, 64 insertions, 0 deletions
diff --git a/FunctorToMaybe.hs b/FunctorToMaybe.hs
new file mode 100644
index 0000000..0fd6b7f
--- /dev/null
+++ b/FunctorToMaybe.hs
@@ -0,0 +1,64 @@
1---------------------------------------------------------------------------
2-- |
3-- Module : FunctorToMaybe
4--
5-- Maintainer : joe@jerkface.net
6-- Stability : experimental
7--
8-- Motivation: When parsing a stream of events, it is often desirable to
9-- let certain control events pass-through to the output stream without
10-- interrupting the parse. For example, the conduit package uses
11-- <http://hackage.haskell.org/package/conduit-1.0.13.1/docs/Data-Conduit.html#t:Flush Flush>
12-- which adds a special command to a stream and the blaze-builder-conduit
13-- package has <http://hackage.haskell.org/package/blaze-builder-conduit-1.0.0/docs/Data-Conduit-Blaze.html#g:2 conduits> that treat the nullary constructor with special significance.
14--
15-- But for other intermediary conduits, the nullary @Flush@ constructor may
16-- be noise that they should politely preserve in case it is meaningul downstream.
17-- If <http://hackage.haskell.org/package/conduit-1.0.13.1/docs/Data-Conduit.html#t:Flush Flush>
18-- implemented the 'FunctorToMaybe' type class, then 'functorToEither' could be used to
19-- seperate the noise from the work-product.
20--
21module FunctorToMaybe where
22
23
24-- | The 'FunctorToMaybe' class genaralizes 'Maybe' in that the
25-- there may be multiple null elements.
26--
27-- Instances of 'FunctorToMaybe' should satisfy the following laws:
28--
29-- > functorToMaybe (fmap f g) == fmap f (functorToMaybe g)
30--
31class Functor g => FunctorToMaybe g where
32 functorToMaybe :: g a -> Maybe a
33
34
35instance FunctorToMaybe Maybe where
36 functorToMaybe = id
37instance FunctorToMaybe (Either a) where
38 functorToMaybe (Right x) = Just x
39 functorToMaybe _ = Nothing
40
41
42-- | 'functorToEither' is a null-preserving cast.
43--
44-- If @functorToMaybe g == Nothing@, then a casted value is returned with Left.
45-- If @functorToMaybe g == Just a@, then @Right a@ is returned.
46--
47-- Returning to our <http://hackage.haskell.org/package/conduit-1.0.13.1/docs/Data-Conduit.html#t:Flush Flush>
48-- example, if we define
49--
50-- > instance Flush where
51-- > functorToMaybe Flush = Nothing
52-- > functorToMaybe (Chunk a) = Just a
53--
54-- Now stream processors can use 'functorToEither' to transform any nullary constructors while
55-- while doing its work to transform the data before forwarding it into
56-- <http://hackage.haskell.org/package/blaze-builder-conduit-1.0.0/docs/Data-Conduit-Blaze.html#v:builderToByteStringFlush builderToByteStringFlush>.
57--
58functorToEither :: FunctorToMaybe f => f a -> Either (f b) a
59functorToEither ga =
60 maybe (Left $ uncast ga)
61 Right
62 (functorToMaybe ga)
63 where
64 uncast = fmap (error "bad FunctorToMaybe instance")