tagged-transformer (empty) → 0.1
raw patch · 4 files changed
+199/−0 lines, 4 filesdep +basedep +transformerssetup-changed
Dependencies added: base, transformers
Files
- Control/Monad/Trans/Tagged.hs +136/−0
- LICENSE +30/−0
- Setup.lhs +7/−0
- tagged-transformer.cabal +26/−0
+ Control/Monad/Trans/Tagged.hs view
@@ -0,0 +1,136 @@+----------------------------------------------------------------------------+-- |+-- Module : Control.Monad.Trans.Tagged+-- Copyright : 2011 Edward Kmett+-- License : BSD3+--+-- Maintainer : Edward Kmett <ekmett@gmail.com>+-- Stability : experimental+-- Portability : portable+--+-------------------------------------------------------------------------------++module Control.Monad.Trans.Tagged+ ( + -- * Tagged values+ Tagged+ , TaggedT(..)+ , retag+ , tag, tagSelf+ , untag, untagSelf+ , asTaggedTypeOf+ ) where++import Prelude hiding (foldr, foldl, mapM, sequence, foldr1, foldl1)+import Control.Applicative+import Control.Monad (liftM, MonadPlus(..))+import Control.Monad.Fix+import Data.Traversable (Traversable(..))+import Data.Foldable (Foldable(..))+import Data.Functor.Identity++-- | A @'Tagged' s b@ value is a value @b@ with an attached phantom type @s@.+-- This can be used in place of the more traditional but less safe idiom of+-- passing in an undefined value with the type, because unlike an @(s -> b)@, +-- a @'Tagged' s b@ can't try to use the argument @s@ as a real value.+--+-- Moreover, you don't have to rely on the compiler to inline away the extra+-- argument, because the newtype is "free"++newtype TaggedT s m b = TagT { untagT :: m b } + deriving ( Eq, Ord, Read, Show )++type Tagged s = TaggedT s Identity++instance Functor m => Functor (TaggedT s m) where + fmap f (TagT x) = TagT (fmap f x)+ b <$ (TagT x) = TagT (b <$ x)+ {-# INLINE fmap #-}++instance Applicative m => Applicative (TaggedT s m) where+ pure = TagT . pure+ {-# INLINE pure #-}+ TagT f <*> TagT x = TagT (f <*> x)+ {-# INLINE (<*>) #-}+ TagT f *> TagT x = TagT (f *> x)+ {-# INLINE ( *>) #-}+ TagT f <* TagT x = TagT (f <* x)+ {-# INLINE (<* ) #-}++instance Alternative m => Alternative (TaggedT s m) where+ empty = TagT empty+ TagT a <|> TagT b = TagT (a <|> b)++instance Monad m => Monad (TaggedT s m) where+ return = TagT . return+ {-# INLINE return #-}+ TagT m >>= k = TagT (m >>= untagT . k)+ {-# INLINE (>>=) #-}+ TagT m >> TagT n = TagT (m >> n)+ {-# INLINE (>>) #-}++instance MonadPlus m => MonadPlus (TaggedT s m) where+ mzero = TagT mzero+ mplus (TagT a) (TagT b) = TagT (mplus a b)++instance MonadFix m => MonadFix (TaggedT s m) where+ mfix f = TagT $ mfix (untagT . f) ++instance Foldable f => Foldable (TaggedT s f) where+ foldMap f (TagT x) = foldMap f x+ {-# INLINE foldMap #-}+ fold (TagT x) = fold x+ {-# INLINE fold #-}+ foldr f z (TagT x) = foldr f z x+ {-# INLINE foldr #-}+ foldl f z (TagT x) = foldl f z x+ {-# INLINE foldl #-}+ foldl1 f (TagT x) = foldl1 f x + {-# INLINE foldl1 #-}+ foldr1 f (TagT x) = foldr1 f x+ {-# INLINE foldr1 #-}++instance Traversable f => Traversable (TaggedT s f) where+ traverse f (TagT x) = TagT <$> traverse f x+ {-# INLINE traverse #-}+ sequenceA (TagT x) = TagT <$> sequenceA x+ {-# INLINE sequenceA #-}+ mapM f (TagT x) = liftM TagT (mapM f x)+ {-# INLINE mapM #-}+ sequence (TagT x) = liftM TagT (sequence x)+ {-# INLINE sequence #-}++-- | Some times you need to change the tag you have lying around.+-- Idiomatic usage is to make a new combinator for the relationship between the+-- tags that you want to enforce, and define that combinator using 'retag'.+--+-- > data Succ n+-- > retagSucc :: Tagged n a -> Tagged (Succ n) a+-- > retagSucc = retag+retag :: TaggedT s m b -> TaggedT t m b+retag = TagT . untagT+{-# INLINE retag #-}++-- | 'asTaggedTypeOf' is a type-restricted version of 'const'. It is usually used as an infix operator, and its typing forces its first argument (which is usually overloaded) to have the same type as the tag of the second.+asTaggedTypeOf :: s -> TaggedT s m b -> s+asTaggedTypeOf = const+{-# INLINE asTaggedTypeOf #-}++tag :: b -> Tagged s b+tag = TagT . Identity+{-# INLINE tag #-}++untag :: Tagged s b -> b+untag = runIdentity . untagT+{-# INLINE untag #-}++-- | Tag a value with its own type.+tagSelf :: a -> Tagged a a+tagSelf = tag+{-# INLINE tagSelf #-}++-- | 'untagSelf' is a type-restricted version of 'untag'.+untagSelf :: Tagged a a -> a+untagSelf = untag+{-# INLINE untagSelf #-}+
+ LICENSE view
@@ -0,0 +1,30 @@+Copyright (c) 2009-2011 Edward Kmett+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.++ * Neither the name of Edward Kmett nor the names of other+ contributors may be used to endorse or promote products derived+ from this software without specific prior written permission.++THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS+"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+OWNER OR CONTRIBUTORS 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.
+ Setup.lhs view
@@ -0,0 +1,7 @@+#!/usr/bin/runhaskell+> module Main (main) where++> import Distribution.Simple++> main :: IO ()+> main = defaultMain
+ tagged-transformer.cabal view
@@ -0,0 +1,26 @@+name: tagged-transformer+version: 0.1+license: BSD3+license-file: LICENSE+author: Edward A. Kmett+maintainer: Edward A. Kmett <ekmett@gmail.com>+stability: experimental+category: Data, Phantom Types+synopsis: Provides newtype wrappers for phantom types to avoid unsafely passing dummy arguments+homepage: http://github.com/ekmett/tagged-transformer+copyright: 2011 Edward A. Kmett+description: Provides newtype wrappers for phantom types to avoid unsafely passing dummy arguments+build-type: Simple+cabal-version: >=1.6++source-repository head+ type: git+ location: git://github.com/ekmett/tagged-transformer.git++library+ build-depends: + base >= 4 && < 5,+ transformers >= 0.2.2 && < 0.3+ exposed-modules:+ Control.Monad.Trans.Tagged+ ghc-options: -Wall