packages feed

flexiwrap 0.0.1 → 0.1.0

raw patch · 27 files changed

+1441/−95 lines, 27 filesdep +QuickCheckdep ~data-type

Dependencies added: QuickCheck

Dependency ranges changed: data-type

Files

+ CHANGES view
@@ -0,0 +1,31 @@+== Version 0.1.0 ==
+
+* Added Data/Flex/Arbitrary.hs (utility module for Arbitrary instances)
+
+* Added instances for Ord, Show, Read, Arbitrary, Monoid to FlexiWrap
+  (Data/Flex/Wrap.hs)
+
+* Added Haddock documentation to
+  Data/Flex/Applicative.hs
+  Data/Flex/Functor.hs
+  Data/Flex/Monad.hs
+  Data/Flex/Utils.hs
+  Data/Flex/Wrap.hs
+
+* Added doc/intro.txt
+
+* Added TODO, README, CHANGES (this file)
+
+* Added Data/Flex/QuickCheck/Wrap.hs test file
+
+* Moved Data/Flex/SmallCheck/Wrap.hs to test/Data/Flex/SmallCheck/Wrap.hs,
+  and added test/.ghci
+
+* New related package flexiwrap-smallcheck containing Serial instances
+  (for FlexiWrap at the moment)
+
+== Version 0.0.1 ==
+
+Initial version
+
+$Header: c:/Source/Haskell/Wrapper/RCS/CHANGES,v 1.1 2011/09/20 23:52:58 dosuser Exp dosuser $
Data/Flex/Applicative.hs view
@@ -2,19 +2,44 @@ {-# LANGUAGE PolymorphicComponents #-}
 {-# LANGUAGE MultiParamTypeClasses #-}
 {-# LANGUAGE FunctionalDependencies #-}
--- .$Header: c:/Source/Haskell/Wrapper/Data/Flex/RCS/Applicative.hs,v 1.1 2010/03/10 01:56:44 dosuser Exp dosuser $
-module Data.Flex.Applicative where
+-- .$Header: c:/Source/Haskell/Wrapper/Data/Flex/RCS/Applicative.hs,v 1.3 2011/09/20 23:35:55 dosuser Exp dosuser $
+module Data.Flex.Applicative (
+    -- * Common flexible Applicative instance selection types and classes
+    -- ** Analysis class for @'Applicative'@ instance selection
+    FWApplicative,
+    -- ** Instance selectors
+    FWDefaultApplicative(..),
+    -- ** Function identifier types for @'Apply'@
+    FWPure(..),
+    FWCombine(..),
+    -- ** Polymorphic function wrappers
+    WrapPure(..),
+    WrapCombine(..)
+) where
 
+-- | Analysis class for @'Applicative'@ instance selection
+-- You need a specific instance of this for any instance selectors
+-- you may define.
 class FWApplicative (f :: * -> *) r | f -> r
 
+-- | Instance selector type for the default @'Applicative'@
+-- instances
 data FWDefaultApplicative = FWDefaultApplicative
 
+-- | Function identifier type for @'Apply'@.
+-- You need a corresponding instance of @'Apply'@ for any
+-- instance selectors you may define.
 data FWPure t (f :: * -> *) = FWPure
 
+-- | Polymorphic function wrapper for @'pure'@
 newtype WrapPure f = WrapPure {unwrapPure :: forall a. a -> f a}
 
+-- | Function identifier type for @'Apply'@.
+-- You need a corresponding instance of @'Apply'@ for any
+-- instance selectors you may define.
 data FWCombine t (f :: * -> *) = FWCombine
 
+-- | Polymorphic function wrapper for @'<*>'@
 newtype WrapCombine f =
     WrapCombine {unwrapCombine :: forall a b. f (a -> b) -> (f a -> f b)}
 
+ Data/Flex/Arbitrary.hs view
@@ -0,0 +1,16 @@+{-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE Rank2Types #-}
+-- .$Header: c:/Source/Haskell/Wrapper/Data/Flex/RCS/Arbitrary.hs,v 1.1 2011/06/10 00:56:23 dosuser Exp dosuser $
+module Data.Flex.Arbitrary (
+    -- * Polymorphic function wrapper
+    WrapCoarbitrary(..)
+) where
+
+import Test.QuickCheck (Gen)
+
+-- | Polymorphic function wrapper for @'coarbitrary'@
+newtype WrapCoarbitrary = WrapCoarbitrary {
+        unwrapCoarbitrary :: forall b. Gen b -> Gen b
+    }
+
+-- vim: expandtab:tabstop=4:shiftwidth=4
Data/Flex/Compose.hs view
@@ -4,7 +4,7 @@ {-# LANGUAGE ScopedTypeVariables #-}
 {-# LANGUAGE Rank2Types #-}
 {-# LANGUAGE OverlappingInstances #-}
--- .$Header: c:/Source/Haskell/Wrapper/Data/Flex/RCS/Compose.hs,v 1.14 2010/12/04 01:40:54 dosuser Exp dosuser $
+-- .$Header: c:/Source/Haskell/Wrapper/Data/Flex/RCS/Compose.hs,v 1.15 2011/03/05 00:55:46 dosuser Exp dosuser $
 module Data.Flex.Compose where
 
 import Control.Monad (liftM, liftM2, join, MonadPlus(..))
Data/Flex/FlipT.hs view
@@ -4,7 +4,7 @@ {-# LANGUAGE MultiParamTypeClasses #-}
 {-# LANGUAGE FlexibleInstances #-}
 {-# LANGUAGE FlexibleContexts #-}
--- .$Header: c:/Source/Haskell/Wrapper/Data/Flex/RCS/FlipT.hs,v 1.8 2010/11/27 00:41:20 dosuser Exp dosuser $
+-- .$Header: c:/Source/Haskell/Wrapper/Data/Flex/RCS/FlipT.hs,v 1.9 2011/03/05 00:57:29 dosuser Exp dosuser $
 module Data.Flex.FlipT where
 
 import Control.Monad (MonadPlus(..))
Data/Flex/Functor.hs view
@@ -1,14 +1,33 @@ {-# LANGUAGE ScopedTypeVariables, PolymorphicComponents #-}
 {-# LANGUAGE MultiParamTypeClasses, FunctionalDependencies #-}
--- .$Header: c:/Source/Haskell/Wrapper/Data/Flex/RCS/Functor.hs,v 1.2 2010/03/12 23:46:00 dosuser Exp dosuser $
-module Data.Flex.Functor where
+-- .$Header: c:/Source/Haskell/Wrapper/Data/Flex/RCS/Functor.hs,v 1.4 2011/09/20 23:36:59 dosuser Exp dosuser $
+module Data.Flex.Functor (
+    -- * Common flexible Functor instance selection types and classes
+    -- ** Analysis class for @'Functor'@ instance selection
+    FWFunctor,
+    -- ** Instance selector
+    FWDefaultFunctor(..),
+    -- ** Function identifier type for @'Apply'@
+    FWFmap(..),
+    -- ** Polymorphic function wrapper
+    WrapFmap(..)
+) where
 
+-- | Analysis class for @'Functor'@ instance selection
+-- You need a specific instance of this for any instance selectors
+-- you may define.
 class FWFunctor (f :: * -> *) r | f -> r
 
+-- | Instance selector type for the default @'Functor'@
+-- instances
 data FWDefaultFunctor = FWDefaultFunctor
 
+-- | Function identifier type for @'Apply'@.
+-- You need a corresponding instance of @'Apply'@ for any
+-- instance selectors you may define.
 data FWFmap t (f :: * -> *) = FWFmap
 
+-- | Polymorphic function wrapper for @'fmap'@
 newtype WrapFmap f =
     WrapFmap {unwrapFmap :: forall a b. (a -> b) -> (f a -> f b)}
 
Data/Flex/Monad.hs view
@@ -1,16 +1,40 @@ {-# LANGUAGE ScopedTypeVariables, Rank2Types #-}
 {-# LANGUAGE MultiParamTypeClasses, FunctionalDependencies #-}
--- .$Header: c:/Source/Haskell/Wrapper/Data/Flex/RCS/Monad.hs,v 1.1 2010/03/10 01:57:35 dosuser Exp dosuser $
-module Data.Flex.Monad where
+-- .$Header: c:/Source/Haskell/Wrapper/Data/Flex/RCS/Monad.hs,v 1.3 2011/09/20 23:37:34 dosuser Exp dosuser $
+module Data.Flex.Monad (
+    -- * Common flexible Monad instance selection types and classes
+    -- ** Analysis class for @'Monad'@ instance selection
+    FWMonad,
+    -- ** Instance selectors
+    FWDefaultMonad(..),
+    -- ** Function identifier types for @'Apply'@
+    FWReturn(..),
+    FWBind(..),
+    -- ** Polymorphic function wrappers
+    WrapReturn(..),
+    WrapBind(..),
+    -- ** Constructor aliases
+    wrapReturn,
+    wrapBind
+) where
 
 -- import Data.Flex.Applicative (WrapPure(..))
 
+-- | Analysis class for @'Monad'@ instance selection
+-- You need a specific instance of this for any instance selectors
+-- you may define.
 class FWMonad (m :: * -> *) r | m -> r
 
+-- | Instance selector type for the default @'Monad'@
+-- instances
 data FWDefaultMonad = FWDefaultMonad
 
+-- | Function identifier type for @'Apply'@.
+-- You need a corresponding instance of @'Apply'@ for any
+-- instance selectors you may define.
 data FWReturn t (m :: * -> *) = FWReturn
 
+-- | Polymorphic function wrapper for @'return'@
 newtype WrapReturn m = WrapReturn {unwrapReturn :: forall a. a -> m a}
 wrapReturn :: (forall a. a -> m a) -> WrapReturn m
 wrapReturn = WrapReturn
@@ -22,8 +46,12 @@ unwrapReturn = unwrapPure
 -}
 
+-- | Function identifier type for @'Apply'@.
+-- You need a corresponding instance of @'Apply'@ for any
+-- instance selectors you may define.
 data FWBind t (m :: * -> *) = FWBind
 
+-- | Polymorphic function wrapper for @'>>='@
 newtype WrapBind m =
     WrapBind {unwrapBind :: forall a b. m a -> (a -> m b) -> m b}
 
Data/Flex/MonadPlus.hs view
@@ -1,6 +1,6 @@ {-# LANGUAGE ScopedTypeVariables, PolymorphicComponents #-}
 {-# LANGUAGE MultiParamTypeClasses, FunctionalDependencies #-}
--- .$Header$
+-- .$Header: c:/Source/Haskell/Wrapper/Data/Flex/RCS/MonadPlus.hs,v 1.2 2011/03/05 01:02:51 dosuser Exp dosuser $
 module Data.Flex.MonadPlus where
 
 class FWMonadPlus (m :: * -> *) r | m -> r
Data/Flex/MonadState.hs view
@@ -1,6 +1,6 @@ {-# LANGUAGE ScopedTypeVariables, PolymorphicComponents #-}
 {-# LANGUAGE MultiParamTypeClasses, FunctionalDependencies #-}
--- .$Header$
+-- .$Header: c:/Source/Haskell/Wrapper/Data/Flex/RCS/MonadState.hs,v 1.1 2011/03/05 01:03:51 dosuser Exp dosuser $
 module Data.Flex.MonadState where
 
 class FWMonadState (m :: * -> *) r | m -> r
Data/Flex/MonadTrans.hs view
@@ -1,7 +1,7 @@ {-# LANGUAGE ScopedTypeVariables, PolymorphicComponents #-}
 {-# LANGUAGE EmptyDataDecls #-}
 {-# LANGUAGE MultiParamTypeClasses, FunctionalDependencies #-}
--- .$Header: c:/Source/Haskell/Wrapper/Data/Flex/RCS/MonadTrans.hs,v 1.2 2010/03/12 23:46:34 dosuser Exp dosuser $
+-- .$Header: c:/Source/Haskell/Wrapper/Data/Flex/RCS/MonadTrans.hs,v 1.3 2011/03/05 01:04:22 dosuser Exp dosuser $
 module Data.Flex.MonadTrans where
 
 class FWMonadTrans (f :: (* -> *) -> (* -> *)) a | f -> a
+ Data/Flex/QuickCheck/Wrap.hs view
@@ -0,0 +1,82 @@+-- $Header: c:/Source/Haskell/Wrapper/Data/Flex/QuickCheck/RCS/Wrap.hs,v 1.1 2011/06/04 00:46:28 dosuser Exp dosuser $
+
+-- | QuickCheck tests for Data.Flex.Wrap
+
+module Data.Flex.QuickCheck.Wrap where
+
+import Test.QuickCheck
+
+import Data.Type.TList (TNil(..), (:*:)(..))
+
+import Data.Flex.Wrap
+
+prop_defaultArbitrary_is_transparent i = forAll rand $ \g ->
+    generate ai g wx == w (generate ai g x)
+  where
+    w = flexiWrap TNil
+    {- N.B. The following circumlocution is necessary because
+        fmap / liftM in the Gen monad split the PRNG
+    -}
+    x = fmap id arbitrary :: Gen Int
+    wx = arbitrary
+    ai = abs i
+
+prop_defaultCoarbitrary_is_transparent i a b = forAll rand $ \g ->
+    generate ai g wx == generate ai g x
+  where
+    ai = abs i
+    w = flexiWrap TNil
+    x = coarbitrary a $ return b
+    wx = coarbitrary (w a) $ return b
+    types = (a :: Int, b :: Int)
+
+prop_transparentArbitrary_is_transparent i = forAll rand $ \g ->
+    generate ai g wx == w (generate ai g x)
+  where
+    w = flexiWrap (FWTransparentArbitrary :*: TNil)
+    {- N.B. The following circumlocution is necessary because
+        fmap / liftM in the Gen monad split the PRNG
+    -}
+    x = fmap id arbitrary :: Gen Int
+    wx = arbitrary
+    ai = abs i
+
+prop_transparentCoarbitrary_is_transparent i a b = forAll rand $ \g ->
+    generate ai g wx == generate ai g x
+  where
+    ai = abs i
+    w = flexiWrap (FWTransparentArbitrary :*: TNil)
+    x = coarbitrary a $ return b
+    wx = coarbitrary (w a) $ return b
+    types = (a :: Int, b :: Int)
+
+prop_explicitDefaultArbitrary_is_transparent i = forAll rand $ \g ->
+    generate ai g wx == w (generate ai g x)
+  where
+    w = flexiWrap (FWDefaultArbitrary :*: TNil)
+    {- N.B. The following circumlocution is necessary because
+        fmap / liftM in the Gen monad split the PRNG
+    -}
+    x = fmap id arbitrary :: Gen Int
+    wx = arbitrary
+    ai = abs i
+
+prop_explicitDefaultCoarbitrary_is_transparent i a b = forAll rand $ \g ->
+    generate ai g wx == generate ai g x
+  where
+    ai = abs i
+    w = flexiWrap (FWDefaultArbitrary :*: TNil)
+    x = coarbitrary a $ return b
+    wx = coarbitrary (w a) $ return b
+    types = (a :: Int, b :: Int)
+
+testArbitrary :: IO ()
+testArbitrary = do
+    quickCheck prop_defaultArbitrary_is_transparent
+    quickCheck prop_defaultCoarbitrary_is_transparent
+    quickCheck prop_transparentArbitrary_is_transparent
+    quickCheck prop_transparentCoarbitrary_is_transparent
+    quickCheck prop_explicitDefaultArbitrary_is_transparent
+    quickCheck prop_explicitDefaultCoarbitrary_is_transparent
+
+-- vim: expandtab:tabstop=4:shiftwidth=4
− Data/Flex/SmallCheck/Wrap.hs
@@ -1,51 +0,0 @@-{-# LANGUAGE FlexibleInstances #-}
-{-# LANGUAGE MultiParamTypeClasses #-}
-{-# LANGUAGE TypeSynonymInstances #-}
-{-# LANGUAGE FlexibleContexts #-}
-{-# LANGUAGE UndecidableInstances #-}
--- $Header: c:/Source/Haskell/Wrapper/Data/Flex/SmallCheck/RCS/Wrap.hs,v 1.2 2010/03/13 00:11:09 dosuser Exp dosuser $
-module Data.Flex.SmallCheck.Wrap where
-
-import Test.SmallCheck
-
-{-
-import Control.Applicative ((<$>))
-
-import Data.Wrap (result, argument)
--}
-
-import Data.Type.Apply (Apply(..))
-import Data.Type.Eq (TypeCast)
-import Data.Type.TList ((:*:), TNil)
-
-import Data.Flex.Wrap
-
-{-
-import Data.Flex.SmallCheck.Instances
--}
-
-data X = X
-
-prop_default_Eq_is_Eq x y = (x == y) == (w x == w y) where
-    w = fWrap X :: Bool -> FW (X :*: TNil) Bool
-    types = x :: Bool
-
-data FWEqFirst = FWEqFirst
-
-instance TypeCast r FWEqFirst => FWEq (FW (FWEqFirst :*: s) a) r
-
-instance Eq a =>
-    Apply (FWEquals t (a, b)) FWEqFirst (FW t (a, b) -> FW t (a, b) -> Bool)
-  where
-    apply _ _ = (==) `on` fst . unFlexiWrap
-
-instance Eq a =>
-    Apply (FWNotEquals t (a, b)) FWEqFirst (FW t (a, b) -> FW t (a, b) -> Bool)
-  where
-    apply _ _ = (/=) `on` fst `on` unFlexiWrap
-
-prop_EqFirst_is_Eq_fst x y = (x `eqFst` y) == (w x == w y) where
-    eqFst = (==) `on` fst
-    w = FlexiWrap :: (Bool, Bool) -> FW (FWEqFirst :*: TNil) (Bool, Bool)
-
--- vim: expandtab:tabstop=4:shiftwidth=4
Data/Flex/Test/Compose.hs view
@@ -1,4 +1,4 @@--- .$Header: c:/Source/Haskell/Wrapper/Data/Flex/Test/RCS/Compose.hs,v 1.5 2010/04/24 00:59:15 dosuser Exp dosuser $
+-- .$Header: c:/Source/Haskell/Wrapper/Data/Flex/Test/RCS/Compose.hs,v 1.6 2011/03/05 01:28:41 dosuser Exp dosuser $
 module Data.Flex.Test.Compose where
 
 import Control.Monad (MonadPlus(..))
Data/Flex/Test/Wrap.hs view
@@ -1,4 +1,4 @@--- $Header: c:/Source/Haskell/Wrapper/Data/Flex/Test/RCS/Wrap.hs,v 1.4 2010/02/05 00:39:46 dosuser Exp dosuser $
+-- $Header: c:/Source/Haskell/Wrapper/Data/Flex/Test/RCS/Wrap.hs,v 1.5 2011/03/05 01:29:46 dosuser Exp dosuser $
 module Data.Flex.Test.Wrap where
 
 import Data.Flex.Wrap
Data/Flex/Test/WrappedMonad.hs view
@@ -1,5 +1,5 @@ {-# LANGUAGE FlexibleContexts #-}
--- .$Header$
+-- .$Header: c:/Source/Haskell/Wrapper/Data/Flex/Test/RCS/WrappedMonad.hs,v 1.4 2011/03/05 01:30:24 dosuser Exp dosuser $
 module Data.Flex.Test.WrappedMonad where
 
 import Control.Applicative (Applicative(..))
Data/Flex/Utils.hs view
@@ -1,27 +1,57 @@ {-# LANGUAGE ScopedTypeVariables, Rank2Types #-}
--- .$Header: c:/Source/Haskell/Wrapper/Data/Flex/RCS/Utils.hs,v 1.1 2010/11/26 23:54:58 dosuser Exp dosuser $
-module Data.Flex.Utils (inCompose, inCompose2, bindWrapper) where
+-- .$Header: c:/Source/Haskell/Wrapper/Data/Flex/RCS/Utils.hs,v 1.5 2011/09/20 23:38:55 dosuser Exp dosuser $
+module Data.Flex.Utils (
+    -- * Various utility functions for handling wrappers
+    -- ** Wrapper/unwrapper composition
+    inCompose, inCompose2,
+    -- ** Constructing @'Monad'@ bind (@'>>='@) for wrapped values
+    bindWrapper,
+    -- ** Another popular composition combinator
+    on
+    -- ** Semantic editor combinators
+    -- (<http://conal.net/blog/posts/semantic-editor-combinators/>)
+    , result, argument
+) where
 
+-- | Place (by composition) two functions round another function
 circumpose :: (c -> d) -> (a -> b) -> (b -> c) -> (a -> d)
 circumpose left right = (left .) . (. right)
 
+-- | Bracket (by composition) a function by two other functions.
+-- (\'In' as in infix.)
+
+-- Sometimes more convenient than @'circumpose'@
 inCompose :: (a -> b) -> (c -> d) -> (b -> c) -> (a -> d)
 inCompose = flip circumpose
 
+-- | A generalisation of @'inCompose'@ to two-argument functions
 inCompose2 :: (forall a. f a -> a) -> (d -> e) ->
     (b -> c -> d) -> (f b -> f c -> e)
 inCompose2 unwrap wrap = inCompose unwrap $ inCompose unwrap wrap
 
+-- | Change the result of a function
 result :: (b -> c) -> (a -> b) -> (a -> c)
 result = (.)
 
--- Utility function to construct (>>=) for a target monad <t> from the (>>=)
--- for an implementation monad <i>
--- Parameters:
---   wrap:   function from target monad to implementation monad (t a -> i a)
---   unwrap: vice versa (i a -> t a)
-bindWrapper :: (forall q. f q -> g q) -> (d -> e) -> (g a -> (c -> g b) -> d) ->
-    f a -> (c -> f b) -> e
+-- | Change the argument of a function
+argument :: (a -> b) -> (b -> c) -> (a -> c)
+argument = flip (.)
+
+-- | Handy utility function
+infixl 8 `on`
+on :: (b -> b -> c) -> (a -> b) -> (a -> a -> c)
+(op `on` f) x y = f x `op` f y
+
+-- | Utility function to construct @'>>='@ for a target monad @t@ from
+-- the @'>>='@ from an implementation monad @i@
+bindWrapper ::
+    (forall q. t q -> i q)
+    -- ^ wrap:   function from target monad to implementation monad
+    -> (d -> e)
+    -- ^ unwrap: vice versa (@i q -> t q@)
+    -> (i a -> (c -> i b) -> d)
+    -- ^ @'>>='@ in the implementation monad
+    -> t a -> (c -> t b) -> e
 bindWrapper wrap unwrap = inCompose wrap $ inCompose (result wrap) unwrap
 
 -- vim: expandtab:tabstop=4:shiftwidth=4
Data/Flex/Wrap.hs view
@@ -1,42 +1,119 @@ {-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE Rank2Types #-}
 {-# LANGUAGE EmptyDataDecls #-}
 {-# LANGUAGE TypeSynonymInstances #-}
 {-# LANGUAGE MultiParamTypeClasses, FunctionalDependencies #-}
 {-# LANGUAGE UndecidableInstances #-}
 {-# LANGUAGE FlexibleInstances #-}
 {-# LANGUAGE OverlappingInstances #-}
--- .$Header: c:/Source/Haskell/Wrapper/Data/Flex/RCS/Wrap.hs,v 1.13 2010/04/24 00:47:40 dosuser Exp dosuser $
-module Data.Flex.Wrap where
+-- .$Header: c:/Source/Haskell/Wrapper/Data/Flex/RCS/Wrap.hs,v 1.18 2011/09/20 23:46:14 dosuser Exp dosuser $
 
+-- | The flexible value wrapper @'FlexiWrap'@ and associated types and classes
+
+module Data.Flex.Wrap (
+    -- * @'FlexiWrap'@
+    -- | and related instance machinery
+
+    -- ** @'FlexiWrap'@
+    -- | with a type synonym and alternative constructors
+    FlexiWrap(..),
+    FW,
+    flexiWrap,
+    flexiWrapP,
+    -- ** Instance selectors
+    FWDefaultEq(..),
+    FWTransparentEq(..),
+    FWDefaultOrd(..),
+    FWTransparentOrd(..),
+    FWReverseOrd(..),
+    FWDefaultShowRead(..),
+    FWLiteralShowRead(..),
+    FWTransparentShowRead(..),
+    FWDefaultArbitrary(..),
+    FWTransparentArbitrary(..),
+    FWDefaultMonoid(..),
+    FWTransparentMonoid(..),
+    FWDualMonoid(..),
+    FWEndoMonoid(..),
+    FWAllMonoid(..),
+    FWAnyMonoid(..),
+    FWSumMonoid(..),
+    FWProductMonoid(..),
+    FWFirstMonoid(..),
+    FWLastMonoid(..),
+    -- ** Machinery for @'Eq'@ instances
+    FWEq,
+    FWEquals(..),
+    FWNotEquals(..),
+    -- ** Machinery for @'Ord'@ instances
+    FWOrd,
+    FWCompare(..),
+    -- ** Machinery for @'Show'@ and @'Read'@ instances
+    FWShowRead,
+    FWShow(..),
+    FWRead(..),
+    -- ** Machinery for @'Arbitrary'@ instances
+    FWArbitraryC,
+    FWArbitrary(..),
+    FWCoarbitrary(..),
+    -- ** Machinery for @'Monoid'@ instances
+    FWMonoid,
+    FWMempty(..),
+    FWMappend(..),
+    -- ** Utility functions
+    inFlexiWrap,
+    inFlexiWrap2,
+    -- * Experimental features
+    FWNormAppend,
+    FWrap(..),
+    FWIsWrapped,
+    FWAlreadyWrapped(..),
+    FWNewWrapper(..)
+) where
+
 import Control.Applicative (Applicative(..))
     -- , (<$>), liftA2, Alternative(..))
 
 import Data.Foldable as F (Foldable(..))
+import Data.Monoid (Monoid(..))
 import qualified Data.Traversable as T (Traversable(..))
 
+import Test.QuickCheck (Arbitrary(..), Gen)
+
 import Data.Type.Apply (Apply(..))
 import Data.Type.Eq (TypeCast)
+import Data.Type.Proxy (Proxy(..))
 import Data.Type.TList ((:*:), TNil)
 
-import Data.Flex.Utils (inCompose, inCompose2)
+import Data.Flex.Arbitrary (WrapCoarbitrary(..))
+import Data.Flex.Utils (inCompose, inCompose2, on)
 
 -- begin FlexiWrap
 
+-- | The flexible value wrapper
 newtype FlexiWrap s a = FlexiWrap {unFlexiWrap :: a}
 
+-- | A handy abbreviated type synonym
 type FW = FlexiWrap
 
+-- | An alternative constructor
 flexiWrap :: s -> a -> FW s a
 flexiWrap _ = FlexiWrap
 
+-- | An alternative constructor using a proxy
+flexiWrapP :: Proxy s -> a -> FW s a
+flexiWrapP _ = FlexiWrap
+
+-- | The implementation of fmap for @'Functor' ('FW' s)@
 inFlexiWrap :: (a -> b) -> (FW s a -> FW s b)
 inFlexiWrap = inCompose unFlexiWrap FlexiWrap
 
+-- | An extension of fmap to two-argument functions
 inFlexiWrap2 :: (a -> b -> c) -> (FW s a -> FW s b -> FW s c)
 -- inFlexiWrap2 = inCompose unFlexiWrap $ inCompose unFlexiWrap FlexiWrap
 inFlexiWrap2 = inCompose2 unFlexiWrap FlexiWrap
 
--- TODO: Use flexible instance machinery
+-- TODO: Use flexible instance machinery?
 
 instance Functor (FW t) where
     fmap = inFlexiWrap
@@ -56,8 +133,10 @@     return = FlexiWrap
     (>>=) = flip (. unFlexiWrap)
 
--- append <s> and <t> to produce <u>
--- <s> may or may not be terminated by TNil
+-- | Utility class to append two type-level lists
+--
+-- append \<s> and \<t> to produce \<u>.
+-- \<s> may or may not be terminated by @'TNil'@;
 -- if so, it does not appear in the result
 class FWNormAppend s t u | s t -> u
 
@@ -67,30 +146,43 @@ 
 instance TypeCast u (x :*: t) => FWNormAppend x t u
 
+-- | Utility class to create or tag-extend a wrapper
+
 -- class FWrap w a b where
 class FWrap w a b | w a -> b where
     fWrap :: w -> a -> b
 
+-- | Analysis class to determine whether an argument is already wrapped,
+-- used for @'FWrap'@
 class FWIsWrapped a r | a -> r
 
+-- | Result type for @'FWIsWrapped'@
 data FWAlreadyWrapped = FWAlreadyWrapped
+-- | Result type for @'FWIsWrapped'@
 data FWNewWrapper = FWNewWrapper
 
+-- | Function identifier type for @'Apply'@
 data FWFWrap s a = FWFWrap
 
 instance FWIsWrapped (FW s a) FWAlreadyWrapped
 instance TypeCast r FWNewWrapper => FWIsWrapped a r
 
+-- | * Implementation instance for @'FWrap'@
 instance Apply (FWFWrap u a) FWNewWrapper (a -> FW u a) where
     apply _ _ = FlexiWrap
+-- | * Implementation instance for @'FWrap'@
 instance Apply (FWFWrap u (FW s a)) FWAlreadyWrapped (FW s a -> FW u a) where
     apply _ _ = FlexiWrap . unFlexiWrap
 
+-- | Function identifier type for @'Apply'@
 data FWTag
 
+-- | * Analysis instance for @'FWTag'@
 instance Apply FWTag (FW t a) t
+-- | * Analysis instance for @'FWTag'@
 instance TypeCast r TNil => Apply FWTag a r
 
+-- | * Coordinating instance definition for @'FWrap'@
 instance forall a b s t u w. (
         Apply FWTag a t,
         FWNormAppend s t u,
@@ -140,31 +232,58 @@     fWrap _ = FlexiWrap
 -}
 
-infixl 8 `on`
-on :: (b -> b -> c) -> (a -> b) -> (a -> a -> c)
-(op `on` f) x y = f x `op` f y
+-- TODO: FWDefaultAll (except Num) selector
 
+-- Eq
+
+-- | Analysis class for @'Eq'@ instance selection.
+-- You need a specific instance of this for any instance selectors
+-- you may define.
 class FWEq a r | a -> r
 
+-- | Instance selector type for the default
+-- (transparent) implementation of @'Eq'@
 data FWDefaultEq = FWDefaultEq
 
+-- | Instance selector type for the (default)
+-- transparent implementation of @'Eq'@
+data FWTransparentEq = FWTransparentEq
+
+-- | Function identifier type for @'Apply'@.
+-- You need a corresponding instance of @'Apply'@ for any
+-- instance selectors you may define.
 data FWEquals t a = FWEquals
 
+-- | Function identifier type for @'Apply'@
+-- You need a corresponding instance of @'Apply'@ for any
+-- instance selectors you may define.
 data FWNotEquals t a = FWNotEquals
 
--- default instance
-instance TypeCast r FWDefaultEq => FWEq (FW t a) r
+-- | * Default instance
+instance TypeCast r FWTransparentEq => FWEq (FW t a) r
 
+-- | * Propagated instance
 instance FWEq (FW s a) r => FWEq (FW (x :*: s) a) r
 
-instance Eq a => Apply (FWEquals t a) FWDefaultEq (FW t a -> FW t a -> Bool)
+-- | * Specific @'FWDefaultEq'@ instance
+instance FWShowRead (FW (FWDefaultEq :*: s) a) FWTransparentEq
+
+-- | * Specific @'FWTransparentEq'@ instance
+instance FWShowRead (FW (FWTransparentEq :*: s) a) FWTransparentEq
+
+-- | * Implementation instance for @'Eq'@ instance selection
+instance Eq a => Apply (FWEquals t a) FWTransparentEq
+    (FW t a -> FW t a -> Bool)
   where
     apply _ _ = (==) `on` unFlexiWrap
 
-instance Eq a => Apply (FWNotEquals t a) FWDefaultEq (FW t a -> FW t a -> Bool)
+-- | * Implementation instance for @'Eq'@ instance selection
+instance Eq a => Apply (FWNotEquals t a) FWTransparentEq
+    (FW t a -> FW t a -> Bool)
   where
     apply _ _ = (/=) `on` unFlexiWrap
 
+-- | * Coordinating instance for @'Eq'@
 instance forall t a r. (Apply (FWEquals t a) r (FW t a -> FW t a -> Bool),
             Apply (FWNotEquals t a) r (FW t a -> FW t a -> Bool),
             FWEq (FW t a) r
@@ -172,6 +291,476 @@         Eq (FW t a) where
     (==) = apply (undefined :: FWEquals t a) (undefined :: r)
     (/=) = apply (undefined :: FWNotEquals t a) (undefined :: r)
+
+-- Ord
+
+-- | Analysis class for @'Ord'@ instance selection
+-- You need a specific instance of this for any instance selectors
+-- you may define.
+class FWOrd a r | a -> r
+
+-- | Instance selector type for the default (transparent) @'Ord'@ instance
+data FWDefaultOrd = FWDefaultOrd
+-- | Instance selector type for the (default) transparent @'Ord'@ instance
+data FWTransparentOrd = FWTransparentOrd
+-- | Instance selector type for a reversed @'Ord'@ instance
+data FWReverseOrd = FWReverseOrd
+
+-- | Function identifier type for @'Apply'@.
+-- You need a corresponding instance of @'Apply'@ for any
+-- instance selectors you may define.
+data FWCompare t a = FWCompare
+
+-- | * Default instance
+instance TypeCast r FWTransparentOrd => FWOrd (FW t a) r
+
+-- | * Propagated instance
+instance FWOrd (FW s a) r => FWOrd (FW (x :*: s) a) r
+
+-- | * Specific @'FWDefaultOrd'@ instance
+instance FWOrd (FW (FWDefaultOrd :*: s) a) FWTransparentOrd
+
+-- | * Specific @'FWTransparentOrd'@ instance
+instance FWOrd (FW (FWTransparentOrd :*: s) a) FWTransparentOrd
+
+-- | * Specific @'FWReverseOrd'@ instance
+instance FWOrd (FW (FWReverseOrd :*: s) a) FWReverseOrd
+
+-- | ** Implementation instance for @'Ord'@ instance selection
+instance Ord a => Apply (Proxy (FWCompare t a)) (Proxy FWTransparentOrd)
+    (FW t a -> FW t a -> Ordering)
+  where
+    apply _ _ = compare `on` unFlexiWrap
+
+-- | ** Implementation instance for @'Ord'@ instance selection
+instance Ord a => Apply (Proxy (FWCompare t a)) (Proxy FWReverseOrd)
+    (FW t a -> FW t a -> Ordering)
+  where
+    apply _ _ = flip compare `on` unFlexiWrap
+
+-- | * Coordinating instance of @'Ord'@
+instance forall t a r. (
+            Apply (Proxy (FWCompare t a)) (Proxy r)
+                (FW t a -> FW t a -> Ordering),
+            FWOrd (FW t a) r,
+            Eq (FW t a)
+        ) =>
+        Ord (FW t a) where
+    compare = apply (Proxy :: Proxy (FWCompare t a)) (Proxy :: Proxy r)
+
+-- Show/Read
+
+app_prec :: Int
+app_prec = 10
+
+-- | Analysis class for @'Show/Read'@ instance selection
+-- You need a specific instance of this for any instance selectors
+-- you may define.
+class FWShowRead a r | a -> r
+
+-- | Instance selector type for the default (literal) @'Show'/'Read'@
+-- instances
+data FWDefaultShowRead = FWDefaultShowRead deriving (Show, Read)
+
+-- | Instance selector type for the (default) literal @'Show'/'Read'@
+-- instances
+data FWLiteralShowRead = FWLiteralShowRead deriving (Show, Read)
+
+-- | Instance selector type for transparent @'Show'/'Read'@ instances
+data FWTransparentShowRead = FWTransparentShowRead deriving (Show, Read)
+
+-- | Function identifier type for @'Apply'@.
+-- You need a corresponding instance of @'Apply'@ for any
+-- instance selectors you may define.
+data FWShow t a = FWShow
+
+-- | Function identifier type for @'Apply'@.
+-- You need a corresponding instance of @'Apply'@ for any
+-- instance selectors you may define.
+data FWRead t a = FWRead
+
+-- | * Default instance
+instance TypeCast r FWLiteralShowRead => FWShowRead (FW t a) r
+
+-- | * Propagated instance
+instance FWShowRead (FW s a) r => FWShowRead (FW (x :*: s) a) r
+
+-- | * Specific @'FWDefaultShowRead'@ instance
+instance FWShowRead (FW (FWDefaultShowRead :*: s) a) FWLiteralShowRead
+
+-- | * Specific @'FWLiteralShowRead'@ instance
+instance FWShowRead (FW (FWLiteralShowRead :*: s) a) FWLiteralShowRead
+
+-- | * Specific @'FWTransparentShowRead'@ instance
+instance FWShowRead (FW (FWTransparentShowRead :*: s) a) FWTransparentShowRead
+
+-- | ** Implementation instance for @'Show'@ instance selection
+instance Show a =>
+    Apply (Proxy (FWShow t a)) (Proxy FWLiteralShowRead)
+        (Int -> FW t a -> ShowS)
+  where
+    apply _ _ d (FlexiWrap w) = showParen (d > app_prec) $
+        showString "FlexiWrap " . showsPrec (app_prec+1) w
+
+-- | ** Implementation instance for @'Read'@ instance selection
+instance Read a =>
+    Apply (Proxy (FWRead t a)) (Proxy FWLiteralShowRead)
+        (Int -> ReadS (FW t a))
+  where
+    apply _ _ d r = readParen
+        (d > app_prec)
+        (\v -> [(FlexiWrap m, t) |
+            ("FlexiWrap", s) <- lex v,
+            (m, t) <- readsPrec (app_prec+1) s
+        ])
+        r
+
+-- | ** Implementation instance for @'Show'@ instance selection
+instance Show a =>
+    Apply (Proxy (FWShow t a)) (Proxy FWTransparentShowRead)
+        (Int -> FW t a -> ShowS)
+  where
+    apply _ _ d (FlexiWrap w) = showParen (d > app_prec) $
+        showsPrec (app_prec+1) w
+
+-- | ** Implementation instance for @'Read'@ instance selection
+instance Read a =>
+    Apply (Proxy (FWRead t a)) (Proxy FWTransparentShowRead)
+        (Int -> ReadS (FW t a))
+  where
+    apply _ _ d r = readParen
+        (d > app_prec)
+        (\s -> [(FlexiWrap m, t) |
+            (m, t) <- readsPrec (app_prec+1) s
+        ])
+        r
+
+-- | * Coordinating instance of @'Show'@
+instance forall t a r. (
+            Apply (Proxy (FWShow t a)) (Proxy r)
+                (Int -> FW t a -> ShowS),
+            FWShowRead (FW t a) r
+        ) =>
+        Show (FW t a) where
+    showsPrec = apply (Proxy :: Proxy (FWShow t a)) (Proxy :: Proxy r)
+
+-- | * Coordinating instance of @'Read'@
+instance forall t a r. (
+            Apply (Proxy (FWRead t a)) (Proxy r)
+                (Int -> ReadS (FW t a)),
+            FWShowRead (FW t a) r
+        ) =>
+        Read (FW t a) where
+    readsPrec = apply (Proxy :: Proxy (FWRead t a)) (Proxy :: Proxy r)
+
+-- Arbitrary
+
+-- | Analysis class for @'Arbitrary'@ instance selection
+-- You need a specific instance of this for any instance selectors
+-- you may define.
+class FWArbitraryC a r | a -> r
+
+-- | Instance selector type for the default (transparent) @'Arbitrary'@
+-- instances
+data FWDefaultArbitrary = FWDefaultArbitrary deriving (Show, Read)
+
+-- | Instance selector type for transparent @'Arbitrary'@ instances
+data FWTransparentArbitrary = FWTransparentArbitrary deriving (Show, Read)
+
+-- | Function identifier type for @'Apply'@.
+-- You need a corresponding instance of @'Apply'@ for any
+-- instance selectors you may define.
+data FWArbitrary t a = FWArbitrary
+
+-- | Function identifier type for @'Apply'@.
+-- You need a corresponding instance of @'Apply'@ for any
+-- instance selectors you may define.
+data FWCoarbitrary t a = FWCoarbitrary
+
+-- | * Default instance
+instance TypeCast r FWTransparentArbitrary => FWArbitraryC (FW t a) r
+
+-- | * Propagated instance
+instance FWArbitraryC (FW s a) r => FWArbitraryC (FW (x :*: s) a) r
+
+-- | * Specific @'FWDefaultArbitrary'@ instance
+instance FWArbitraryC (FW (FWDefaultArbitrary :*: s) a) FWTransparentArbitrary
+
+-- | * Specific @'FWTransparentArbitrary'@ instance
+instance FWArbitraryC (FW (FWTransparentArbitrary :*: s) a)
+    FWTransparentArbitrary
+
+-- | ** Implementation instance for @'Arbitrary'@ instance selection
+instance Arbitrary a =>
+    Apply (Proxy (FWArbitrary t a)) (Proxy FWTransparentArbitrary)
+        (Gen (FW t a))
+  where
+    apply _ _  = fmap FlexiWrap arbitrary
+
+-- | ** Implementation instance for @'Arbitrary'@ instance selection
+instance Arbitrary a =>
+    Apply (Proxy (FWCoarbitrary t a)) (Proxy FWTransparentArbitrary)
+        (FW t a -> WrapCoarbitrary)
+  where
+    apply _ _  x = WrapCoarbitrary (coarbitrary $ unFlexiWrap x)
+
+-- | * Coordinating instance of @'Arbitrary'@
+instance forall t a r. (
+            Apply (Proxy (FWArbitrary t a)) (Proxy r) (Gen (FW t a)),
+            Apply (Proxy (FWCoarbitrary t a)) (Proxy r)
+                (FW t a -> WrapCoarbitrary),
+            FWArbitraryC (FW t a) r
+        ) =>
+        Arbitrary (FW t a) where
+    arbitrary = apply (Proxy :: Proxy (FWArbitrary t a)) (Proxy :: Proxy r)
+    coarbitrary = unwrapCoarbitrary .
+        apply (Proxy :: Proxy (FWCoarbitrary t a)) (Proxy :: Proxy r)
+
+-- Monoid
+
+-- | Analysis class for @'Monoid'@ instance selection
+-- You need a specific instance of this for any instance selectors
+-- you may define.
+class FWMonoid a r | a -> r
+
+-- | Instance selector type for the default (transparent) @'Monoid'@
+-- instances
+data FWDefaultMonoid = FWDefaultMonoid deriving (Show, Read)
+
+-- | Instance selector type for transparent @'Monoid'@ instances
+data FWTransparentMonoid = FWTransparentMonoid deriving (Show, Read)
+
+-- | Instance selector type for dual @'Monoid'@ instances,
+-- obtained by swapping the arguments of 'mappend'.
+data FWDualMonoid = FWDualMonoid deriving (Show, Read)
+
+-- Internal version of FWDualMonoid, capturing the subsequent
+-- instance selectors
+data FWDualMonoidI s = FWDualMonoidI deriving (Show, Read)
+
+-- | Instance selector type for instances of the @'Monoid'@ of
+-- endomorphisms under composition.
+data FWEndoMonoid = FWEndoMonoid deriving (Show, Read)
+
+-- | Instance selector type for instances of the Boolean
+-- @'Monoid'@ under conjunction.
+data FWAllMonoid = FWAllMonoid deriving (Show, Read)
+
+-- | Instance selector type for instances of the Boolean
+-- @'Monoid'@ under disjunction.
+data FWAnyMonoid = FWAnyMonoid deriving (Show, Read)
+
+-- | Instance selector type for instances of a numeric
+-- @'Monoid'@ under addition.
+data FWSumMonoid = FWSumMonoid deriving (Show, Read)
+
+-- | Instance selector type for instances of a numeric
+-- @'Monoid'@ under multiplication.
+data FWProductMonoid = FWProductMonoid deriving (Show, Read)
+
+-- | Instance selector type for instances of a
+-- Maybe @'Monoid'@ returning the leftmost non-Nothing value.
+data FWFirstMonoid = FWFirstMonoid deriving (Show, Read)
+
+-- | Instance selector type for instances of a
+-- Maybe @'Monoid'@ returning the rightmost non-Nothing value.
+data FWLastMonoid = FWLastMonoid deriving (Show, Read)
+
+-- | Function identifier type for @'Apply'@.
+-- You need a corresponding instance of @'Apply'@ for any
+-- instance selectors you may define.
+data FWMempty t a = FWMempty
+
+-- | Function identifier type for @'Apply'@.
+-- You need a corresponding instance of @'Apply'@ for any
+-- instance selectors you may define.
+data FWMappend t a = FWMappend
+
+-- | * Default instance
+instance TypeCast r FWTransparentMonoid => FWMonoid (FW t a) r
+
+-- | * Propagated instance
+instance FWMonoid (FW s a) r => FWMonoid (FW (x :*: s) a) r
+
+-- | * Specific @'FWDefaultMonoid'@ instance
+instance FWMonoid (FW (FWDefaultMonoid :*: s) a) FWTransparentMonoid
+
+-- | * Specific @'FWTransparentMonoid'@ instance
+instance FWMonoid (FW (FWTransparentMonoid :*: s) a) FWTransparentMonoid
+
+-- | * Specific @'FWDualMonoid'@ instance
+instance FWMonoid (FW (FWDualMonoid :*: s) a) (FWDualMonoidI s)
+
+-- | * Specific @'FWEndoMonoid'@ instance
+instance FWMonoid (FW (FWEndoMonoid :*: s) a) FWEndoMonoid
+
+-- | * Specific @'FWAllMonoid'@ instance
+instance FWMonoid (FW (FWAllMonoid :*: s) a) FWAllMonoid
+
+-- | * Specific @'FWAnyMonoid'@ instance
+instance FWMonoid (FW (FWAnyMonoid :*: s) a) FWAnyMonoid
+
+-- | * Specific @'FWSumMonoid'@ instance
+instance FWMonoid (FW (FWSumMonoid :*: s) a) FWSumMonoid
+
+-- | * Specific @'FWProductMonoid'@ instance
+instance FWMonoid (FW (FWProductMonoid :*: s) a) FWProductMonoid
+
+-- | * Specific @'FWFirstMonoid'@ instance
+instance FWMonoid (FW (FWFirstMonoid :*: s) a) FWFirstMonoid
+
+-- | * Specific @'FWLastMonoid'@ instance
+instance FWMonoid (FW (FWLastMonoid :*: s) a) FWLastMonoid
+
+-- | ** Implementation instance for @'Monoid'@ instance selection
+instance Monoid a =>
+    Apply (Proxy (FWMempty t a)) (Proxy FWTransparentMonoid) (FW t a)
+  where
+    apply _ _  = FlexiWrap mempty
+
+-- | ** Implementation instance for @'Monoid'@ instance selection
+instance Monoid a =>
+    Apply (Proxy (FWMappend t a)) (Proxy FWTransparentMonoid)
+        (FW t a -> FW t a -> FW t a)
+  where
+    apply _ _  = inFlexiWrap2 mappend
+
+-- | ** Implementation instance for @'Monoid'@ instance selection
+instance forall a t s. Monoid (FW s a) =>
+    Apply (Proxy (FWMempty t a)) (Proxy (FWDualMonoidI s)) (FW t a)
+  where
+    apply _ _  = FlexiWrap $ unFlexiWrap me
+      where
+        me = mempty :: FW s a
+
+-- TODO: Move inCompose2R to Data.Flex.Utils
+
+-- | ** Implementation instance for @'Monoid'@ instance selection
+instance forall a t s. Monoid (FW s a) =>
+    Apply (Proxy (FWMappend t a)) (Proxy (FWDualMonoidI s))
+        (FW t a -> FW t a -> FW t a)
+  where
+    apply _ _  = inCompose2R unwrap wrap $ flip mappend
+      where
+        inCompose2R :: (forall v. p v -> q v) -> (q d -> e) ->
+            (q b -> q c -> q d) ->
+            (p b -> p c -> e)
+        inCompose2R down up = inCompose down $ inCompose down up
+        unwrap :: FW t b -> FW s b
+        unwrap = FlexiWrap . unFlexiWrap
+        wrap :: FW s a -> FW t a
+        wrap = FlexiWrap . unFlexiWrap
+
+-- | ** Implementation instance for @'Monoid'@ instance selection
+instance Apply (Proxy (FWMempty t (a -> a))) (Proxy FWEndoMonoid)
+    (FW t (a -> a))
+  where
+    apply _ _  = FlexiWrap id
+
+-- | ** Implementation instance for @'Monoid'@ instance selection
+instance Apply (Proxy (FWMappend t (a -> a))) (Proxy FWEndoMonoid)
+        (FW t (a -> a) -> FW t (a -> a) -> FW t (a -> a))
+  where
+    apply _ _  = inFlexiWrap2 (.)
+
+-- | ** Implementation instance for @'Monoid'@ instance selection
+instance Apply (Proxy (FWMempty t Bool)) (Proxy FWAllMonoid) (FW t Bool)
+  where
+    apply _ _  = FlexiWrap True
+
+-- | ** Implementation instance for @'Monoid'@ instance selection
+instance Apply (Proxy (FWMappend t Bool)) (Proxy FWAllMonoid)
+        (FW t Bool -> FW t Bool -> FW t Bool)
+  where
+    apply _ _  = inFlexiWrap2 (&&)
+
+-- | ** Implementation instance for @'Monoid'@ instance selection
+instance Apply (Proxy (FWMempty t Bool)) (Proxy FWAnyMonoid) (FW t Bool)
+  where
+    apply _ _  = FlexiWrap False
+
+-- | ** Implementation instance for @'Monoid'@ instance selection
+instance Apply (Proxy (FWMappend t Bool)) (Proxy FWAnyMonoid)
+        (FW t Bool -> FW t Bool -> FW t Bool)
+  where
+    apply _ _  = inFlexiWrap2 (||)
+
+-- | ** Implementation instance for @'Monoid'@ instance selection
+instance Num a =>
+    Apply (Proxy (FWMempty t a)) (Proxy FWSumMonoid) (FW t a)
+  where
+    apply _ _  = FlexiWrap 0
+
+-- | ** Implementation instance for @'Monoid'@ instance selection
+instance Num a =>
+    Apply (Proxy (FWMappend t a)) (Proxy FWSumMonoid)
+        (FW t a -> FW t a -> FW t a)
+  where
+    apply _ _  = inFlexiWrap2 (+)
+
+-- | ** Implementation instance for @'Monoid'@ instance selection
+instance Num a =>
+    Apply (Proxy (FWMempty t a)) (Proxy FWProductMonoid) (FW t a)
+  where
+    apply _ _  = FlexiWrap 1
+
+-- | ** Implementation instance for @'Monoid'@ instance selection
+instance Num a =>
+    Apply (Proxy (FWMappend t a)) (Proxy FWProductMonoid)
+        (FW t a -> FW t a -> FW t a)
+  where
+    apply _ _  = inFlexiWrap2 (*)
+
+-- | ** Implementation instance for @'Monoid'@ instance selection
+instance Apply (Proxy (FWMempty t (Maybe a))) (Proxy FWFirstMonoid)
+    (FW t (Maybe a))
+  where
+    apply _ _  = FlexiWrap Nothing
+
+-- | ** Implementation instance for @'Monoid'@ instance selection
+instance Apply (Proxy (FWMappend t (Maybe a))) (Proxy FWFirstMonoid)
+        (FW t (Maybe a) -> FW t (Maybe a) -> FW t (Maybe a))
+  where
+    apply _ _  = inFlexiWrap2 f
+      where
+        r@(Just _) `f` _ = r
+        Nothing    `f` r = r
+
+-- | ** Implementation instance for @'Monoid'@ instance selection
+instance Apply (Proxy (FWMempty t (Maybe a))) (Proxy FWLastMonoid)
+    (FW t (Maybe a))
+  where
+    apply _ _  = FlexiWrap Nothing
+
+-- | ** Implementation instance for @'Monoid'@ instance selection
+instance Apply (Proxy (FWMappend t (Maybe a))) (Proxy FWLastMonoid)
+        (FW t (Maybe a) -> FW t (Maybe a) -> FW t (Maybe a))
+  where
+    apply _ _  = inFlexiWrap2 f
+      where
+        _ `f` r@(Just _) = r
+        r `f` Nothing    = r
+
+-- TODO: Min, Max monoids
+
+-- | * Coordinating instance of @'Monoid'@
+instance forall t a r. (
+            Apply (Proxy (FWMempty t a)) (Proxy r) (FW t a),
+            Apply (Proxy (FWMappend t a)) (Proxy r)
+                (FW t a -> FW t a -> FW t a),
+            FWMonoid (FW t a) r
+        ) =>
+        Monoid (FW t a) where
+    mempty = apply (Proxy :: Proxy (FWMempty t a)) (Proxy :: Proxy r)
+    mappend = apply (Proxy :: Proxy (FWMappend t a)) (Proxy :: Proxy r)
+
+{- TODO:
+    Num and it's subclasses
+    Bounded, Enum, Ix
+    Data, Typeable
+    Binary
+    NFData
+-}
 
 -- end FlexiWrap
 
Data/Flex/WrapCTC.hs view
@@ -4,7 +4,7 @@ {-# LANGUAGE FlexibleInstances #-}
 {-# LANGUAGE UndecidableInstances #-}
 {-# LANGUAGE OverlappingInstances #-}
--- .$Header: c:/Source/Haskell/Wrapper/Data/Flex/RCS/WrapCTC.hs,v 1.4 2010/12/01 00:24:20 dosuser Exp dosuser $
+-- .$Header: c:/Source/Haskell/Wrapper/Data/Flex/RCS/WrapCTC.hs,v 1.5 2011/03/05 01:10:38 dosuser Exp dosuser $
 module Data.Flex.WrapCTC where
 
 import Control.Monad (MonadPlus(..))
Data/Flex/WrapT.hs view
@@ -5,7 +5,7 @@ {-# LANGUAGE TypeSynonymInstances #-}
 {-# LANGUAGE UndecidableInstances #-}
 {-# LANGUAGE OverlappingInstances #-}
--- .$Header: c:/Source/Haskell/Wrapper/Data/Flex/RCS/WrapT.hs,v 1.9 2010/12/01 00:37:45 dosuser Exp dosuser $
+-- .$Header: c:/Source/Haskell/Wrapper/Data/Flex/RCS/WrapT.hs,v 1.10 2011/03/05 01:15:44 dosuser Exp dosuser $
 module Data.Flex.WrapT where
 
 import Control.Applicative (Applicative(..))
Data/Flex/WrappedMonad.hs view
@@ -1,7 +1,7 @@ {-# LANGUAGE FlexibleInstances #-}
 {-# LANGUAGE TypeSynonymInstances #-}
 {-# LANGUAGE MultiParamTypeClasses #-}
--- .$Header: c:/Source/Haskell/Wrapper/Data/Flex/RCS/WrappedMonad.hs,v 1.2 2010/02/10 00:26:03 dosuser Exp dosuser $
+-- .$Header: c:/Source/Haskell/Wrapper/Data/Flex/RCS/WrappedMonad.hs,v 1.3 2011/03/05 01:12:40 dosuser Exp dosuser $
 module Data.Flex.WrappedMonad where
 
 import Control.Monad (liftM, ap)
LICENSE view
@@ -1,4 +1,4 @@-Copyright Iain Alexander 2010.
+Copyright Iain Alexander 2011.
 All rights reserved.
 
 Redistribution and use in source and binary forms, with or without
+ README view
@@ -0,0 +1,12 @@+README for flexiwrap version 0.1.0
+
+Use Cabal (http://www.haskell.org/cabal/) to install.
+
+See doc/intro.txt for an introduction to the concepts.
+
+Tests are currently in local subdirectories {QuickCheck, SmallCheck, Test}
+as appropriate, apart from one in the <test> directory.
+The ones in the Test subdirectory are compile-time only tests -
+just load them in ghci.
+
+$Header: c:/Source/Haskell/Wrapper/RCS/README,v 1.1 2011/09/20 23:54:23 dosuser Exp dosuser $
+ TODO view
@@ -0,0 +1,14 @@+Known work outstanding for flexiwrap-0.1.0:
+
+More typeclasses still needed for FlexiWrap
+(see TODO comments in Data/Flex/Wrap.hs)
+N.B. some of these may go in separate modules.
+
+More typeclasses for FlexiWrapT (Data/Flex/WrapT.hs)
+and FlexiWrapCTC (Data/Flex/WrapCTC.hs), not commented
+
+More Haddock (and other) documentation
+
+Move the rest of the tests into the <test> subdirectory
+
+$Header: c:/Source/Haskell/Wrapper/RCS/TODO,v 1.1 2011/09/20 23:57:38 dosuser Exp dosuser $
+ doc/intro.txt view
@@ -0,0 +1,155 @@+Subject: Flexible Wrappers - an Introduction
+
+There are three flexible wrappers provided in the current flexiwrap
+package [1].  (More may be required in the future.)
+
+    short   long            wraps
+    FW      FlexiWrap       values
+    FWT     FlexiWrapT      unary type constructors
+    FWCTC   FlexiWrapCTC    binary operators which combine two
+                            unary type constructors
+
+The short names are frequently convenient since type signatures can
+get quite long.  The suffixes are a simple encoding of the kind
+of the wrapped quantity, description of which I defer till later.
+
+The first parameter to each of these is a phantom - it plays no part
+in the implementation type, but serves as an index to generate multiple
+distinct types from each wrapper.
+In addition, by using a type-level list here, we can use it to specify
+any number of instance implementations.
+
+By way of a rather simple example, the module Data.Flex.SmallCheck.Wrap
+in the test subdirectory
+uses an instance selector called FWReverseOrd to request an
+Ord instance which compares values in reverse order,
+which you might compare to the Down newtype.  It is used there by
+using the phantom parameter (FWReverseOrd :*: TNil) resulting in the
+(implied) type
+
+    FW (FWReverseOrd :*: TNil) Bool
+
+which has the requisite properties.
+
+The current version of the package provides
+only a limited number of instance selectors (with the associated
+machinery) for each wrapper.
+Many of the supplied instances simply delegate to the underlying wrapped type.
+
+FW (in Data.Flex.Wrap)
+
+FWTransparentEq (delegates Eq)
+FWDefaultEq (alias for FWTransparentEq)
+FWTransparentOrd (delegates Ord)
+FWDefaultOrd (alias for FWTransparentOrd)
+FWReverseOrd (reverses the arguments for Ord)
+FWTransparentShowRead (delegates Show and Read)
+FWLiteralShowRead (prefixes "FlexiWrap " to the value from the delegated
+    Show instance, and correspondingly for Read)
+FWDefaultShowRead (alias for FWLiteralShowRead)
+FWTransparentArbitrary (delegates Arbitrary)
+FWDefaultArbitrary (alias for FWTransparentArbitrary)
+FWTransparentMonoid (delegates Monoid)
+FWDefaultMonoid (alias for FWTransparentMonoid)
+FWEndoMonoid (cf. newtype Endo)
+FWAllMonoid (cf. newtype All)
+FWAnyMonoid (cf. newtype Any)
+FWSumMonoid (cf. newtype Sum)
+FWProductMonoid (cf. newtype Product)
+FWFirstMonoid (cf. newtype First)
+FWLastMonoid (cf. newtype Last)
+FWDualMonoid (reverses the arguments for the Monoid instance,
+    such that e.g. (FWDualMonoid :*: FWFirstMonoid :*: TNil)
+    is equivalent to (FWLastMonoid :*: TNil)
+
+There is a separate package flexiwrap-smallcheck which supplies instances
+of Serial, currently only for FW.
+
+FWT (Data.Flex.WrapT) has
+
+FWTDefaultFunctor (Functor)
+FWTDefaultApplicative (Applicative)
+FWTDefaultMonadAll (the combination of FWTDefaultMonad and
+    FWTDefaultMonadState)
+FWTDefaultMonad (Monad)
+FWTDefaultMonadState (MonadState)
+
+which all again delegate to the underlying type.
+
+There is also a separate module Data.Flex.WrappedMonad which
+provides selectors to implement Functor and Applicative instances
+for a Monad which lacks them.
+
+FWWrapMonad (the combination of FWMonadFunctor and FWMonadApplicative)
+FWMonadFunctor (Monad => Functor)
+FWMonadApplicative (Monad => Applicative)
+
+FWCTC (Data.Flex.WrapCTC) has
+
+FWCTCDefaultFunctor (Functor)
+FWCTCDefaultMonad (Monad)
+
+which simply delegate to the application of the wrapped binary operator
+to two constructor arguments, but provides underlying machinery for
+these together with MonadPlus and MonadTrans.
+
+Data.Flex.Compose contains the (:.) (alias O) type composition operator
+as found in e.g. the TypeCompose package [2].  It contains a fairly
+literal translation of Mark Jones and Luc Duponcheel's scheme for
+monad composition [3],
+
+FWCompP - use the "prod" construction
+FWCompD - use the "dorp" construction
+FWCompS - use the "swap" construction
+
+and selectors for MonadTrans and MonadPlus
+
+FWCompDefaults (the combination of FWCompTrans and FWCompMonadPlus)
+FWCompTrans (MonadTrans)
+FWCompMonadPlus (a synonym for FWCompMonadPlusR)
+FWCompMonadPlusR (using the MonadPlus instance of the right-hand
+    argument of the composition)
+FWCompMonadPlusL (using the MonadPlus instance of the left-hand
+    argument of the composition)
+
+Data.Flex.FlipT contains the operator FlipT which flips the
+arguments of an operator such as (:.).
+
+FWFlipDefaults (the combination of FWFlipMonad and FWFlipMonadPlus)
+FWFlipMonad (Monad)
+FWFlipMonadPlus (MonadPlus)
+
+These delegate the implementation to the underlying binary operator,
+which it wraps with FWCTC, passing the phantom selector list along.
+
+So, to recap the example given in the initial package release announcement:
+
+data FWStrict = FWStrict
+
+type Strict = FW (FWStrict :*: TNil)
+
+type StrictT = FWCTC
+    (FWFlipDefaults :*:
+        FWCompMonadPlusL :*: FWCompDefaults :*: FWCompS :*: TNil
+    )
+    (FlipT O) Strict
+
+defines a (e.g. monad, but in general constructor) transformer StrictT.
+FWCTC is a flexible wrapper.  Its first parameter is an HList-like type-level
+list of instance specifications.  O is the type composition operator,
+and FlipT flips its arguments.  Strict is a user-defined wrapper type.
+(This is strict vs. loose, not strict vs. lazy.  It is intended to be
+used to wrap values of a data structure which satisfy certain criteria.)
+FWCompMonadPlusL specifies a particular MonadPlus instance (which
+delegates to the left operand of the composition, which is the right
+operand of the flipped composition, i.e. whatever argument you pass
+to StrictT), and FWCompS specifies the Jones/Duponcheel SComp
+construction [3].  The other two items in the list (apart from the
+TNil terminator) specify default implementations of other instances.
+
+[1] http://hackage.haskell.org/package/flexiwrap-0.1.0
+[2] http://hackage.haskell.org/package/TypeCompose
+[3] http://web.cecs.pdx.edu/~mpj/pubs/RR-1004.pdf
+
+$Header: c:/Source/Haskell/Wrapper/doc/RCS/intro.txt,v 1.3 2011/09/14 01:22:32 dosuser Exp dosuser $
+-- vim: expandtab:tabstop=4:shiftwidth=4
flexiwrap.cabal view
@@ -1,5 +1,5 @@ Name:            flexiwrap
-Version:         0.0.1
+Version:         0.1.0
 Cabal-version:   >= 1.2.3
 Build-Type:      Simple
 Synopsis:        Flexible wrappers
@@ -11,7 +11,8 @@ Author:          Iain Alexander <ia@stryx.demon.co.uk>
 Maintainer:      Iain Alexander <ia@stryx.demon.co.uk>
 Build-Type:      Simple
-Extra-source-files:   Data/Flex/SmallCheck/Wrap.hs
+Extra-source-files:   Data/Flex/QuickCheck/Wrap.hs
+                    , test/Data/Flex/SmallCheck/Wrap.hs
                     , Data/Flex/Test/Compose.hs
                     , Data/Flex/Test/Wrap.hs
                     , Data/Flex/Test/WrappedMonad.hs
@@ -19,10 +20,16 @@                     , Data/Flex/Examples/Lex/Strict.hs
                     , Data/Wrap.hs
                     , .ghci
+                    , test/.ghci
+                    , README
+                    , CHANGES
+                    , TODO
+                    , doc/intro.txt
 Tested-with:     GHC==6.4.1, GHC==6.6.1, GHC==6.8.3, GHC==6.10.4, GHC==6.12.3
-               , GHC==7.0.1
+               , GHC==7.0.1, GHC==7.0.4
 Library
     Exposed-Modules:     Data.Flex.Applicative
+                       , Data.Flex.Arbitrary
                        , Data.Flex.Compose
                        , Data.Flex.FlipT
                        , Data.Flex.Functor
@@ -42,5 +49,6 @@         Ghc-options:     -fglasgow-exts
     if impl(ghc >= 6.8.1)
         Extensions:      TypeOperators, KindSignatures
-    Build-Depends:   base < 5, data-type < 0.1, mtl < 2.1
+    Build-Depends:   base < 5, data-type >= 0.1 && < 0.2, mtl < 2.1
+                   , QuickCheck
 -- vim: expandtab:tabstop=4:shiftwidth=4
+ test/.ghci view
@@ -0,0 +1,3 @@+let extensions= (const . return $ let version = Data.Version.versionBranch System.Info.compilerVersion in if version < [6, 6] then ":set -fglasgow-exts -fallow-undecidable-instances -fallow-overlapping-instances" else if version >= [6, 8] then ":set -XTypeOperators -XKindSignatures" else "") :: String -> IO String
+:def extensions extensions
+:extensions
+ test/Data/Flex/SmallCheck/Wrap.hs view
@@ -0,0 +1,385 @@+{-# LANGUAGE FlexibleInstances #-}
+{-# LANGUAGE MultiParamTypeClasses #-}
+{-# LANGUAGE TypeSynonymInstances #-}
+{-# LANGUAGE FlexibleContexts #-}
+{-# LANGUAGE UndecidableInstances #-}
+-- $Header: c:/Source/Haskell/Wrapper/test/Data/Flex/SmallCheck/RCS/Wrap.hs,v 1.9 2011/09/20 23:50:10 dosuser Exp dosuser $
+
+-- | SmallCheck tests for Data.Flex.Wrap
+
+module Data.Flex.SmallCheck.Wrap where
+
+import Test.SmallCheck
+
+{-
+import Control.Applicative ((<$>))
+
+import Data.Wrap (result, argument)
+-}
+
+import Data.Monoid (Monoid(..))
+
+import Data.Type.Apply (Apply(..))
+import Data.Type.Eq (TypeCast)
+import Data.Type.TList ((:*:)(..), TNil(..))
+
+import Data.Flex.Wrap
+import Data.Flex.Utils (on)
+
+import Data.Flex.Serial.Wrap ()
+
+{-
+import Data.Flex.SmallCheck.Instances
+-}
+
+data X = X
+
+-- Eq
+
+prop_default_Eq_is_Eq x y = (x == y) == (w x == w y) where
+    w = flexiWrap (X :*: TNil)
+    types = x :: Bool
+
+prop_explicit_DefaultEq_is_Eq x y = (x == y) == (w x == w y) where
+    w = flexiWrap (FWDefaultEq :*: TNil)
+    types = x :: Bool
+
+prop_TransparentEq_is_Eq x y = (x == y) == (w x == w y) where
+    w = flexiWrap (FWTransparentEq :*: TNil)
+    types = x :: Bool
+
+data FWEqFirst = FWEqFirst
+
+instance TypeCast r FWEqFirst => FWEq (FW (FWEqFirst :*: s) a) r
+
+instance Eq a =>
+    Apply (FWEquals t (a, b)) FWEqFirst (FW t (a, b) -> FW t (a, b) -> Bool)
+  where
+    apply _ _ = (==) `on` fst . unFlexiWrap
+
+instance Eq a =>
+    Apply (FWNotEquals t (a, b)) FWEqFirst (FW t (a, b) -> FW t (a, b) -> Bool)
+  where
+    apply _ _ = (/=) `on` fst `on` unFlexiWrap
+
+prop_EqFirst_is_Eq_fst x y = (x `eqFst` y) == (w x == w y) where
+    eqFst = (==) `on` fst
+    w = flexiWrap (FWEqFirst :*: TNil)
+    types = x :: (Bool, Bool)
+
+testEq :: IO ()
+testEq = do
+    smallCheck 1 prop_default_Eq_is_Eq
+    smallCheck 1 prop_explicit_DefaultEq_is_Eq
+    smallCheck 1 prop_TransparentEq_is_Eq
+    smallCheck 1 prop_EqFirst_is_Eq_fst
+
+-- Ord
+
+prop_default_Ord_is_Ord x y = (x `compare` y) == (w x `compare` w y) where
+    w = flexiWrap (X :*: TNil)
+    types = x :: Bool
+
+prop_explicit_DefaultOrd_is_Ord x y = (x `compare` y) == (w x `compare` w y)
+  where
+    w = flexiWrap (FWDefaultOrd :*: TNil)
+    types = x :: Bool
+
+prop_TransparentOrd_is_Ord x y = (x `compare` y) == (w x `compare` w y) where
+    w = flexiWrap (FWTransparentOrd :*: TNil)
+    types = x :: Bool
+
+prop_ReverseOrd_is_reverse_ord x y = (x `compare` y) == (w y `compare` w x)
+  where
+    w = flexiWrap (FWReverseOrd :*: TNil)
+    types = x :: Bool
+
+testOrd :: IO ()
+testOrd = do
+    smallCheck 1 prop_default_Ord_is_Ord
+    smallCheck 1 prop_explicit_DefaultOrd_is_Ord
+    smallCheck 1 prop_TransparentOrd_is_Ord
+    smallCheck 1 prop_ReverseOrd_is_reverse_ord
+
+-- Show / Read
+
+prop_default_Show_is_Literal x = show (w x) == "FlexiWrap " ++ show x
+  where
+    w = flexiWrap TNil
+    types = x :: Bool
+
+prop_default_Read_is_Literal x = read ("FlexiWrap " ++ show x) == w x
+  where
+    w = flexiWrap TNil
+    types = x :: Bool
+
+prop_explicit_default_Show_is_Literal x = show (w x) == "FlexiWrap " ++ show x
+  where
+    w = flexiWrap (FWDefaultShowRead :*: TNil)
+    types = x :: Bool
+
+prop_explicit_default_Read_is_Literal x = read ("FlexiWrap " ++ show x) == w x
+  where
+    w = flexiWrap (FWDefaultShowRead :*: TNil)
+    types = x :: Bool
+
+prop_Literal_Show_is_Literal x = show (w x) == "FlexiWrap " ++ show x
+  where
+    w = flexiWrap (FWLiteralShowRead :*: TNil)
+    types = x :: Bool
+
+prop_Literal_Read_is_Literal x = read ("FlexiWrap " ++ show x) == w x
+  where
+    w = flexiWrap (FWLiteralShowRead :*: TNil)
+    types = x :: Bool
+
+prop_Transparent_Show_is_Transparent x = show (w x) == show x
+  where
+    w = flexiWrap (FWTransparentShowRead :*: TNil)
+    types = x :: Bool
+
+prop_Transparent_Read_is_Transparent x = read (show x) == w x
+  where
+    w = flexiWrap (FWTransparentShowRead :*: TNil)
+    types = x :: Bool
+
+prop_default_ShowRead_roundtrips x = (read . show) wx == wx
+  where
+    wx = flexiWrap TNil x
+    types = x :: Bool
+
+prop_LiteralShowRead_roundtrips x = (read . show) wx == wx
+  where
+    wx = flexiWrap (FWLiteralShowRead :*: TNil) x
+    types = x :: Bool
+
+prop_TransparentShowRead_roundtrips x = (read . show) wx == wx
+  where
+    wx = flexiWrap (FWTransparentShowRead :*: TNil) x
+    types = x :: Bool
+
+testShowRead :: IO ()
+testShowRead = do
+    smallCheck 1 prop_default_Show_is_Literal
+    smallCheck 1 prop_default_Read_is_Literal
+    smallCheck 1 prop_explicit_default_Show_is_Literal
+    smallCheck 1 prop_explicit_default_Read_is_Literal
+    smallCheck 1 prop_Literal_Show_is_Literal
+    smallCheck 1 prop_Literal_Read_is_Literal
+    smallCheck 1 prop_Transparent_Show_is_Transparent
+    smallCheck 1 prop_Transparent_Read_is_Transparent
+    smallCheck 1 prop_default_ShowRead_roundtrips
+    smallCheck 1 prop_LiteralShowRead_roundtrips
+    smallCheck 1 prop_TransparentShowRead_roundtrips
+
+-- Monoid
+
+prop_DefaultMonoid_mempty_is_transparent = mempty == w me
+  where
+    w = flexiWrap TNil
+    me = mempty :: [Bool]
+
+prop_DefaultMonoid_mappend_is_transparent x y =
+    w x `mappend` w y == w (x `mappend` y)
+  where
+    w = flexiWrap TNil
+    types = x :: [Bool]
+
+prop_explicit_DefaultMonoid_mempty_is_transparent = mempty == w me
+  where
+    w = flexiWrap (FWDefaultMonoid :*: TNil)
+    me = mempty :: [Bool]
+
+prop_explicit_DefaultMonoid_mappend_is_transparent x y =
+    w x `mappend` w y == w (x `mappend` y)
+  where
+    w = flexiWrap (FWDefaultMonoid :*: TNil)
+    types = x :: [Bool]
+
+prop_TransparentMonoid_mempty_is_transparent = mempty == w me
+  where
+    w = flexiWrap (FWTransparentMonoid :*: TNil)
+    me = mempty :: [Bool]
+
+prop_TransparentMonoid_mappend_is_transparent x y =
+    w x `mappend` w y == w (x `mappend` y)
+  where
+    w = flexiWrap (FWTransparentMonoid :*: TNil)
+    types = x :: [Bool]
+
+prop_DualMonoid_mempty_is_dual = mempty == w me
+  where
+    w = flexiWrap (FWDualMonoid :*: TNil)
+    me = mempty :: [Bool]
+
+prop_DualMonoid_mappend_is_dual x y =
+    w x `mappend` w y == w (y `mappend` x)
+  where
+    w = flexiWrap (FWDualMonoid :*: TNil)
+    types = x :: [Bool]
+
+f `feq` g = forAll series $ \z -> f z == g z
+wfeq = feq `on` unFlexiWrap
+
+prop_EndoMonoid_mempty_is_id = mempty `wfeq` w idb
+  where
+    w = flexiWrap (FWEndoMonoid :*: TNil)
+    idb = id :: Bool -> Bool
+
+prop_EndoMonoid_mappend_is_composition x y =
+    (w x `mappend` w y) `wfeq` w (x . y)
+  where
+    w = flexiWrap (FWEndoMonoid :*: TNil)
+    types = x :: Bool -> Bool
+
+prop_AllMonoid_mempty_is_True = mempty == w True
+  where
+    w = flexiWrap (FWAllMonoid :*: TNil)
+
+prop_AllMonoid_mappend_is_conjunction x y =
+    w x `mappend` w y == w (x && y)
+  where
+    w = flexiWrap (FWAllMonoid :*: TNil)
+    types = x :: Bool
+
+prop_DualAllMonoid_mempty_is_True = mempty == w True
+  where
+    w = flexiWrap (FWDualMonoid :*: FWAllMonoid :*: TNil)
+
+prop_DualAllMonoid_mappend_is_conjunction x y =
+    w x `mappend` w y == w (x && y)
+  where
+    w = flexiWrap (FWDualMonoid :*: FWAllMonoid :*: TNil)
+    types = x :: Bool
+
+prop_AnyMonoid_mempty_is_False = mempty == w False
+  where
+    w = flexiWrap (FWAnyMonoid :*: TNil)
+
+prop_AnyMonoid_mappend_is_disjunction x y =
+    w x `mappend` w y == w (x || y)
+  where
+    w = flexiWrap (FWAnyMonoid :*: TNil)
+    types = x :: Bool
+
+prop_DualAnyMonoid_mempty_is_False = mempty == w False
+  where
+    w = flexiWrap (FWDualMonoid :*: FWAnyMonoid :*: TNil)
+
+prop_SumMonoid_mempty_is_zero = mempty == w z
+  where
+    w = flexiWrap (FWSumMonoid :*: TNil)
+    z = 0 :: Int
+
+prop_SumMonoid_mappend_is_addition x y =
+    w x `mappend` w y == w (x + y)
+  where
+    w = flexiWrap (FWSumMonoid :*: TNil)
+    types = x :: Int
+
+prop_DualSumMonoid_mempty_is_zero = mempty == w z
+  where
+    w = flexiWrap (FWDualMonoid :*: FWSumMonoid :*: TNil)
+    z = 0 :: Int
+
+prop_ProductMonoid_mempty_is_one = mempty == w o
+  where
+    w = flexiWrap (FWProductMonoid :*: TNil)
+    o = 1 :: Int
+
+prop_ProductMonoid_mappend_is_multiplication x y =
+    w x `mappend` w y == w (x * y)
+  where
+    w = flexiWrap (FWProductMonoid :*: TNil)
+    types = x :: Int
+
+prop_DualProductMonoid_mappend_is_multiplication x y =
+    w x `mappend` w y == w (x * y)
+  where
+    w = flexiWrap (FWDualMonoid :*: FWProductMonoid :*: TNil)
+    types = x :: Int
+
+prop_FirstMonoid_mempty_is_Nothing = mempty == w n
+  where
+    w = flexiWrap (FWFirstMonoid :*: TNil)
+    n = Nothing :: Maybe Bool
+
+prop_FirstMonoid_mempty_mappend_is_id x =
+    mempty `mappend` x == x
+  where
+    types = x :: FW (FWFirstMonoid :*: TNil) (Maybe Bool)
+
+prop_FirstMonoid_Just_mappend_is_const x y =
+    wx `mappend` y == wx
+  where
+    w = flexiWrap (FWFirstMonoid :*: TNil)
+    wx = w $ Just x
+    types = (x :: Bool, y :: FW (FWFirstMonoid :*: TNil) (Maybe Bool))
+
+prop_LastMonoid_mempty_is_Nothing = mempty == w n
+  where
+    w = flexiWrap (FWLastMonoid :*: TNil)
+    n = Nothing :: Maybe Bool
+
+prop_LastMonoid_mappend_mempty_is_id x =
+    x `mappend` mempty == x
+  where
+    types = x :: FW (FWLastMonoid :*: TNil) (Maybe Bool)
+
+prop_LastMonoid_mappend_Just_is_const x y =
+    y `mappend` wx == wx
+  where
+    w = flexiWrap (FWLastMonoid :*: TNil)
+    wx = w $ Just x
+    types = (x :: Bool, y :: FW (FWLastMonoid :*: TNil) (Maybe Bool))
+
+prop_DualFirstMonoid_mappend_is_Last x y =
+    wdf x `mappend` wdf y `uweq` wl x `mappend` wl y
+  where
+    wdf = flexiWrap (FWDualMonoid :*: FWFirstMonoid :*: TNil)
+    wl = flexiWrap (FWLastMonoid :*: TNil)
+    infix 4 `uweq`
+    uweq u v = unFlexiWrap u == unFlexiWrap v
+    types = (x :: Maybe Bool, y :: Maybe Bool)
+
+testMonoid :: IO ()
+testMonoid = do
+    smallCheck 0 prop_DefaultMonoid_mempty_is_transparent
+    smallCheck 1 prop_DefaultMonoid_mappend_is_transparent
+    smallCheck 0 prop_explicit_DefaultMonoid_mempty_is_transparent
+    smallCheck 1 prop_explicit_DefaultMonoid_mappend_is_transparent
+    smallCheck 0 prop_TransparentMonoid_mempty_is_transparent
+    smallCheck 1 prop_TransparentMonoid_mappend_is_transparent
+    smallCheck 0 prop_DualMonoid_mempty_is_dual
+    smallCheck 1 prop_DualMonoid_mappend_is_dual
+    smallCheck 0 prop_EndoMonoid_mempty_is_id
+    smallCheck 1 prop_EndoMonoid_mappend_is_composition
+    smallCheck 0 prop_AllMonoid_mempty_is_True
+    smallCheck 1 prop_AllMonoid_mappend_is_conjunction
+    smallCheck 0 prop_DualAllMonoid_mempty_is_True
+    smallCheck 1 prop_DualAllMonoid_mappend_is_conjunction
+    smallCheck 0 prop_AnyMonoid_mempty_is_False
+    smallCheck 1 prop_AnyMonoid_mappend_is_disjunction
+    smallCheck 0 prop_DualAnyMonoid_mempty_is_False
+    smallCheck 0 prop_SumMonoid_mempty_is_zero
+    smallCheck 1 prop_SumMonoid_mappend_is_addition
+    smallCheck 0 prop_DualSumMonoid_mempty_is_zero
+    smallCheck 0 prop_ProductMonoid_mempty_is_one
+    smallCheck 1 prop_ProductMonoid_mappend_is_multiplication
+    smallCheck 1 prop_DualProductMonoid_mappend_is_multiplication
+    smallCheck 0 prop_FirstMonoid_mempty_is_Nothing
+    smallCheck 1 prop_FirstMonoid_mempty_mappend_is_id
+    smallCheck 1 prop_FirstMonoid_Just_mappend_is_const
+    smallCheck 0 prop_LastMonoid_mempty_is_Nothing
+    smallCheck 1 prop_LastMonoid_mappend_mempty_is_id
+    smallCheck 1 prop_LastMonoid_mappend_Just_is_const
+    smallCheck 1 prop_DualFirstMonoid_mappend_is_Last
+
+testAll :: IO ()
+testAll = do
+    testEq
+    testOrd
+    testShowRead
+    testMonoid
+
+-- vim: expandtab:tabstop=4:shiftwidth=4