Skip to content

Commit

Permalink
Initial version of library
Browse files Browse the repository at this point in the history
  • Loading branch information
snoyberg committed Jun 28, 2010
1 parent ef33d46 commit 1f47000
Show file tree
Hide file tree
Showing 4 changed files with 136 additions and 0 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
*.swp
/dist
80 changes: 80 additions & 0 deletions Data/Neither.hs
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
25 changes: 25 additions & 0 deletions LICENSE
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.
29 changes: 29 additions & 0 deletions neither.cabal
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

0 comments on commit 1f47000

Please sign in to comment.