Changes to Typeable

Gábor Lehel illissius at gmail.com
Thu Oct 4 23:19:24 CEST 2012


On Thu, Oct 4, 2012 at 10:58 PM, Tyson Whitehead <twhitehead at gmail.com> wrote:
> On October 4, 2012 13:48:42 Ben Millwood wrote:
>> On Thu, Oct 4, 2012 at 5:03 PM, Tyson Whitehead <twhitehead at gmail.com>
>> > import Data.Typeable
>> > import Data.Maybe
>> >
>> > magic :: Typeable a => a -> a
>> > magic x =
>> >
>> >   case cast x of
>> >
>> >     Just x -> cast $ fromJust $ x ++ " (ta da)"
>> >     _  -> x
>> >
>> > gives you id except for strings.
>>
>> ITYM fromJust $ cast rather than the other way around. But the ability
>> to cast like this does not give you access to data structure you
>> didn't already have – it does not violate abstraction.
>
> Indeed.  I did mean those to be swapped.  Thanks for picking up on that.
>
> I have to confess though, I'm not really following on how this doesn't give
> you access to data structure you didn't already have?  Perhaps we are not
> thinking of the same thing when you say "access to data structure"?
>
> Doesn't the above "a -> a" function (under the proposed system where you don't
> need a "Typeable a" constraint") take apart some of its argument
>
> magic 1 ---> 1
> magic 2 ---> 2
> magic "hello world" ---> "hello world (ta da)"
>
> Doesn't this mean then that whole "theorems for free" stuff goes out the
> window?  Isn't its whole basis the idea that unconstrained types are actually
> statements that those arguments won't be constructed/deconstructed?
>
> Thanks!  -Tyson

You still need a Typeable constraint!

There would *not* be an

    instance Typeable a

there would only be

    instance Typeable Foo
    instance Typeable Bar
    instance Typeable Baz
    ...

for every concrete type that is declared. But there's no universal
instance, and there's no way to take advantage of the fact that every
particular type has an instance.

If you had

    foo :: a -> a

and it was doing things like you described, that would be a big
problem! But as discussed previously, that _will not_ happen. You will
still need a Typeable constraint to be able to use typeOf and cast.

On the other hand if you have

    bar :: Typeable a => a -> a

and it did those, it's unremarkable (it can already do those things).
That's a very different type signature from what 'foo' has.

The change would be that you could you use 'bar' with any _concrete_
types you supply (so 'Int', or 'Bool', or 'MyData', 'Foo', 'Bar', or
'Baz', but not 'a' or 'b'), instead of only the ones that explicitly
have 'deriving Typeable'.

The question is whether that's bad in any way -- whether there's any
case where you do *not* want a particular type to be an instance of
Typeable. The classic case where you do not want a type to implement a
class is when the instance would expose implementation details of the
type which you want to keep hidden (for example if want to hide data
constructors, Data or Generic would be purpose-defeating). So the
questions are:

(1) Does Typeable expose anything internal to a type which you might
want to keep hidden (I don't think so)

(2) Are there any other reasons you might want to avoid having an
instance (I can't think of any)


-- 
Your ship was destroyed in a monadic eruption.



More information about the Libraries mailing list