This is getting off-topic, but... I don't like this solution at all :). It is very dependent on read being a true inverse of show, which isn't always the case. Perhaps more importantly though, I don't like the fact that it will readily convert between Int and Float, etc. For instance, in almost all of my applications I use something that looks like:
> newtype Log = Log !Double where 'show (Log d) = show (exp l)' and 'read s = Log (log (read s))'. If I wanted to have a function applied to only Logs, having it also applied to Floats/Doubles/etc because of the show/read connection would be very bad and would require me to wrap things up in more and more constructors just to get unique show instances. Not to mention that it's terribly inefficient. If our concern is to stay within a standard subset of Haskell, using H98+FFI, we get unsafePerformIO with which we can write unsafeCoerce. Using simply String ids as in the referenced paper would make this sort-of-safe, provided users don't give bogus instances of Typeable. -- Hal Daume III | [EMAIL PROTECTED] "Arrest this man, he talks in maths." | www.isi.edu/~hdaume On Mon, 24 Mar 2003 [EMAIL PROTECTED] wrote: > > Hello! > > The paper > http://research.microsoft.com/~simonpj/papers/hmap/ > by Ralf Laemmel and Simon Peyton Jones gave a reference > implementation of a 'cast' function. Here's another implementation: > > cast:: (Show a, Read b) => a -> Maybe b > > cast = read_as . show > where > read_as s = case readsPrec 1 s of > [(r,[])] -> Just r > _ -> Nothing > > > -- Tests from the hmap paper > > -- *Main> (cast 'a') :: Maybe Char > -- Just 'a' > -- *Main> (cast 'a') :: Maybe Int > -- Nothing > -- *Main> (cast 'a') :: Maybe Bool > -- Nothing > -- *Main> (cast True) :: Maybe Bool > -- Just True > -- *Main> (cast "True") :: Maybe Bool > -- Nothing > -- *Main> (cast "True") :: Maybe Int > -- Nothing > -- *Main> (cast "True") :: Maybe String > -- Just "True" > > -- Additional tests > > -- *Main> (cast [1,2,3])::Maybe [Int] > -- Just [1,2,3] > -- *Main> (cast [1,2,3])::Maybe [Integer] > -- Just [1,2,3] > -- *Main> (cast [1,2,3])::Maybe [Float] > -- Just [1.0,2.0,3.0] > -- *Main> (cast (Just True)) :: Maybe Int > -- Nothing > -- *Main> (cast (Just True)) :: Maybe (Maybe Bool) > -- Just (Just True) > -- *Main> (cast (Nothing::Maybe Bool)) :: Maybe (Maybe Bool) > -- Just Nothing > -- *Main> (cast (Nothing::Maybe Bool)) :: Maybe (Maybe Int) > -- Just Nothing > -- *Main> (cast (Nothing::Maybe Bool)) :: Maybe (Maybe Char) > -- Just Nothing > > > Granted, the cast function here cannot handle exponential types. OTH, > the cast function given here can cast an Int to an Integer or to a Float. Most > of all, the cast function here is implemented entirely in Haskell 98, > with no extensions whatsoever -- not existential types, let alone > unsafeCoerce. > > > An aside: OCaml has a function called Obj.magic: 'a -> 'b, > which is unsafeCoerce with a positive name. If OCaml did not provide > that function, it can be easily emulated: > > # let door_to_hell x = > Marshal.from_string (Marshal.to_string () []) 0;; > val door_to_hell : 'a -> 'b = <fun> > > This is a terminating function with a signature a->b. It critically > relies on marshalling and unmarshalling. BTW, the function breaks all > kinds of free theorems: > > # let (fake_id: 'a->'a) = function x -> door_to_hell x;; > val fake_id : 'a -> 'a = <fun> > # fake_id 123;; > - : int = 0 > > We can write a totally polymorphic terminating function a->a that is > patently not the identity. > _______________________________________________ > Haskell mailing list > [EMAIL PROTECTED] > http://www.haskell.org/mailman/listinfo/haskell > _______________________________________________ Haskell mailing list [EMAIL PROTECTED] http://www.haskell.org/mailman/listinfo/haskell