Data.Fixed.Fixed constructor

David Menendez dave at zednenem.com
Thu Jul 23 22:53:09 EDT 2009


On Thu, Jul 23, 2009 at 10:06 PM, David Menendez<dave at zednenem.com> wrote:
> On Thu, Jul 23, 2009 at 3:29 PM, Ashley Yakeley<ashley at semantic.org> wrote:
>> On Thu, 2009-07-23 at 14:07 +0100, Jules Bean wrote:
>>> Ashley Yakeley wrote:
>>> > I'm currently working on updating the Data.Fixed module in base. I am
>>> > adding Typeable and Data instances (automatically derived), and several
>>> > new HasResolution types (including one for 10^-2, monetary currencies
>>> > being an obvious Fixed use).
>>>
>>> Is an automatic Data instance wise?
>>>
>>> Morally speaking does a Data.Fixed really "include" a Integer?
>>>
>>> Compare the question: should the automatic Data instance for Complex a
>>> be used, since this exposes the fact that Complex is stored using two
>>> components in real/imaginary components?
>>>
>>> I think that abstract types like Complex and Fixed should be treated as
>>> atoms by Data rather than being traversable, but I'm not sure.
>>
>> Could you give me an example of a Data instance for either Complex or
>> Fixed that you approve of?
>>
>> Data instances unavoidably expose concrete structure. That may be the
>> actual internal structure of the type, or it may be some constructed
>> concrete structure, but it must be something.
>
> For Fixed, perhaps something along the lines of the Double instance?
>
> doubleType :: DataType
> doubleType = mkFloatType "Prelude.Double"
>
> instance Data Double where
>  toConstr = mkFloatConstr floatType   -- that should probably be "doubleType"
>  gunfold _ z c = case constrRep c of
>                    (FloatConstr x) -> z x
>                    _ -> error "gunfold"
>  dataTypeOf _ = doubleType
>
> You'd just need to insert some appropriate conversions between Double and Fixed.
>
> Alternatively, you could make Fixed non-representable like Ptr,
>
> instance Typeable a => Data (Ptr a) where
>  toConstr _   = error "toConstr"
>  gunfold _ _  = error "gunfold"
>  dataTypeOf _ = mkNorepType "GHC.Ptr.Ptr"
>
> Note that both these instances use the default definition for gfoldl,
> which does not attempt to descend into the structure of the data. I
> think this is appropriate, although whoever wrote the instance for
> Ratio appears to disagree with me.

I just checked the second SYB paper,
<http://www.cs.vu.nl/boilerplate/gmap2.pdf>, and in section 5.2 it
discusses primitive types. Based on that, I think StringRep is the
most correct solution.

Here's a quick sketch that seems to work:

> import Data.Typeable
> import Data.Data
> import Data.Fixed
>
> instance (HasResolution a) => Typeable (Fixed a) where
>     -- omitted
>
> fixedType :: DataType
> fixedType = mkStringType "Data.Fixed.Fixed"
>
> instance (HasResolution a) => Data (Fixed a) where
>     toConstr x = mkStringConstr fixedType (show x)
>     dataTypeOf _ = fixedType
>
>     gunfold _ z c = case constrRep c of
>                         StringConstr s -> z (readFixed s)
>                         _ -> error "gunfold"
>
> readFixed :: HasResolution a => String -> Fixed a
> readFixed s = realToFrac x
>     where
>     x :: Double
>     x = read s


-- 
Dave Menendez <dave at zednenem.com>
<http://www.eyrie.org/~zednenem/>


More information about the Libraries mailing list