You can use ExistentialQuantification in your SortOpts type. The following compilations:
{-
However, note that you cannot use binType as a function because it will have a type of type exists a. SortOpts -> a exists a. SortOpts -> a , and you cannot use existential types as return values. However, you can get the field value from the pattern, for example
test :: SortOpts -> ByteString -> ByteString -> Ordering test (SortOpts{binType=binType}) bsa bsb = compare ab where a = runGet get bsa `asTypeOf` binType b = runGet get bsb `asTypeOf` binType
This deserializes and compares two bytes using the existential binType in the given SortOpts .
As you noticed, Haskell's syntax does not support existential fields, so you need to do something like this to update binType :
defaultOpts = SortOpts { maxFiles = 128 , maxMemory = 1000 * 1000 * 1000 * 1000 , maxThreads = 4 , binType = 0 :: Word32 } alternativeOpts = withBinType (0 :: Word16) $ defaultOpts { maxFiles = 256 } withBinType :: (Bits a, Binary a, Ord a) => a -> SortOpts -> SortOpts withBinType bt (SortOpts{..}) = SortOpts maxFiles maxMemory maxThreads bt
The above example uses RecordWildCards to make copying a record easier. It is also a convenient extension when using parameter writing later.
Alternatively, as jozefg suggested, you can use the shell type for binType . You would use it as follows:
{-
Since SortOpts now only a regular recording type, you can use all write operations normally. To reference the deployed binType , you need to match pattern matching with the wrapper, so the test example from earlier would be (using RecordWildCards )
test :: SortOpts -> ByteString -> ByteString -> Ordering test (SortOpts{..}) bsa bsb = case binType of BinType bt -> compare ab where a = runGet get bsa `asTypeOf` bt b = runGet get bsb `asTypeOf` bt
Note that all of the above assumes that you have a specific use case in which for some reason you need to hide the exact type parameter behind the existential one. Usually you just leave the type parameter in SortOpts and restrict it to functions that use SortOpts . I.e.
data SortOpts a = SortOpts { maxFiles :: Int , maxMemory :: Integer , maxThreads :: Int , binType :: a } test :: (Bits a, Binary a, Ord a) => SortOpts a -> ByteString -> ByteString -> Ordering test (SortOpts{..}) bsa bsb = compare ab where a = runGet get bsa `asTypeOf` binType b = runGet get bsb `asTypeOf` binType
You can use the ConstraintKinds extension to create a shorter alias if necessary, as in
{-