diff options
Diffstat (limited to 'FunctorToMaybe.hs')
-rw-r--r-- | FunctorToMaybe.hs | 64 |
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 | -- | ||
21 | module 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 | -- | ||
31 | class Functor g => FunctorToMaybe g where | ||
32 | functorToMaybe :: g a -> Maybe a | ||
33 | |||
34 | |||
35 | instance FunctorToMaybe Maybe where | ||
36 | functorToMaybe = id | ||
37 | instance 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 | -- | ||
58 | functorToEither :: FunctorToMaybe f => f a -> Either (f b) a | ||
59 | functorToEither ga = | ||
60 | maybe (Left $ uncast ga) | ||
61 | Right | ||
62 | (functorToMaybe ga) | ||
63 | where | ||
64 | uncast = fmap (error "bad FunctorToMaybe instance") | ||