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