forked from snoyberg/neither
-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
4 changed files
with
136 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
*.swp | ||
/dist |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,80 @@ | ||
{-# LANGUAGE DeriveDataTypeable #-} | ||
{-# LANGUAGE PackageImports #-} | ||
-- | This module provides three different datatypes: 'AEither' is the | ||
-- applicative version of Either. It does not provide a monad instance, and | ||
-- 'mappend's together error values. 'MEither' is the monadic version, which | ||
-- only holds onto the first error value. 'MEitherT' is a monad transformer. | ||
module Data.Neither | ||
( -- * Applicative version | ||
AEither (..) | ||
, aeither | ||
-- * Monadic version | ||
, MEither (..) | ||
, meither | ||
-- * Monad transformer | ||
, MEitherT (..) | ||
, mapMEitherT | ||
) where | ||
|
||
import Prelude hiding (catch) | ||
import Control.Applicative | ||
import Control.Monad | ||
import Data.Typeable | ||
import Data.Data | ||
import Data.Monoid | ||
import Control.Monad.IO.Class | ||
import Control.Monad.Trans.Class | ||
import "MonadCatchIO-transformers" Control.Monad.CatchIO (MonadCatchIO (..)) | ||
|
||
data MEither a b = MLeft a | MRight b | ||
deriving (Typeable, Eq, Data, Ord, Read, Show) | ||
instance Monad (MEither a) where | ||
return = MRight | ||
(MLeft a) >>= _ = MLeft a | ||
(MRight b) >>= f = f b | ||
instance Functor (MEither a) where | ||
fmap = liftM | ||
instance Applicative (MEither a) where | ||
pure = return | ||
(<*>) = ap | ||
meither :: (a -> c) -> (b -> c) -> MEither a b -> c | ||
meither f _ (MLeft a) = f a | ||
meither _ f (MRight b) = f b | ||
|
||
data AEither a b = ALeft a | ARight b | ||
deriving (Typeable, Eq, Data, Ord, Read, Show) | ||
instance Functor (AEither a) where | ||
fmap _ (ALeft a) = ALeft a | ||
fmap f (ARight b) = ARight $ f b | ||
instance Monoid a => Applicative (AEither a) where | ||
pure = ARight | ||
ALeft x <*> ALeft y = ALeft $ x `mappend` y | ||
ALeft x <*> _ = ALeft x | ||
_ <*> ALeft y = ALeft y | ||
ARight x <*> ARight y = ARight $ x y | ||
aeither :: (a -> c) -> (b -> c) -> AEither a b -> c | ||
aeither f _ (ALeft a) = f a | ||
aeither _ f (ARight b) = f b | ||
|
||
newtype MEitherT e m a = MEitherT | ||
{ runMEitherT :: m (MEither e a) | ||
} | ||
mapMEitherT :: (m (MEither e a) -> n (MEither e' b)) | ||
-> MEitherT e m a | ||
-> MEitherT e' n b | ||
mapMEitherT f m = MEitherT $ f (runMEitherT m) | ||
|
||
instance Functor m => Functor (MEitherT e m) where | ||
fmap f = MEitherT . fmap (fmap f) . runMEitherT | ||
instance Monad m => Monad (MEitherT e m) where | ||
return = MEitherT . return . return | ||
(MEitherT x) >>= f = MEitherT $ | ||
x >>= meither (return . MLeft) (runMEitherT . f) | ||
instance MonadTrans (MEitherT e) where | ||
lift = MEitherT . liftM MRight | ||
instance MonadIO m => MonadIO (MEitherT e m) where | ||
liftIO = lift . liftIO | ||
instance MonadCatchIO m => MonadCatchIO (MEitherT e m) where | ||
m `catch` f = mapMEitherT (\m' -> m' `catch` \e -> runMEitherT $ f e) m | ||
block = mapMEitherT block | ||
unblock = mapMEitherT unblock |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
The following license covers this documentation, and the source code, except | ||
where otherwise indicated. | ||
|
||
Copyright 2010, Michael Snoyman. All rights reserved. | ||
|
||
Redistribution and use in source and binary forms, with or without | ||
modification, are permitted provided that the following conditions are met: | ||
|
||
* Redistributions of source code must retain the above copyright notice, this | ||
list of conditions and the following disclaimer. | ||
|
||
* Redistributions in binary form must reproduce the above copyright notice, | ||
this list of conditions and the following disclaimer in the documentation | ||
and/or other materials provided with the distribution. | ||
|
||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS "AS IS" AND ANY EXPRESS OR | ||
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF | ||
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO | ||
EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY DIRECT, INDIRECT, | ||
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | ||
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, | ||
OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF | ||
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE | ||
OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF | ||
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
name: neither | ||
version: 0.0.0 | ||
license: BSD3 | ||
license-file: LICENSE | ||
author: Michael Snoyman <[email protected]> | ||
maintainer: Michael Snoyman <[email protected]> | ||
synopsis: Provide versions of Either with good monad and applicative instances. | ||
description: | ||
The standard Either datatype suffers from a lack of monad and applicative instances. To make matters worse, the mtl and transformers packages provide orphan instances which conflict with each other, as well as defining a transformer version which has an usually unnecessary superclass constraint. | ||
. | ||
Besides these annoyances, there is another issue: there exist two reasonable definitions of the Applicative instance for Either: one the holds onto only the first Left value, or one that appends all Left values together via a Monoid instance. The former is compatible with the monad instance, while the latter is not. | ||
. | ||
This package defines three datatypes, some helpers functions and instances. The data types are AEither, MEither and MEitherT. AEither provides an Applicative instance which appends Left values, MEither provides the monadic definition, and MEitherT is a monad transformer. | ||
category: Data | ||
stability: Stable | ||
cabal-version: >= 1.6 | ||
build-type: Simple | ||
homepage: http://github.com/snoyberg/neither | ||
|
||
library | ||
build-depends: base >= 4 && < 5, | ||
transformers >= 0.2.1 && < 0.3, | ||
MonadCatchIO-transformers >= 0.2.2 && < 0.3 | ||
exposed-modules: Data.Neither | ||
ghc-options: -Wall | ||
|
||
source-repository head | ||
type: git | ||
location: git://github.com/snoyberg/neither.git |