
There are three flexible wrappers provided in the initial 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 to a later post. 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 contrived but simple example, the module Data.Flex.SmallCheck.Wrap implements and uses an instance selector called FWEqFirst to implement an Eq instance which compares pairs by their first element. It is used there by defining a type FW (FWEqFirst :*: TNil) (Bool, Bool) which has the requisite properties. The initial proof-of-concept version of the package provides only a limited number of instance selectors (with the associated machinery) for each wrapper. FW (in Data.Flex.Wrap) has only an implementation for Eq instances, with FWDefaultEq to explicitly specify the default implementation which simply delegates to the underlying wrapped type. 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 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.0.1 [2] http://hackage.haskell.org/package/TypeCompose [3] http://web.cecs.pdx.edu/~mpj/pubs/RR-1004.pdf