
Dan Licata: Thanks for explaining the mechanics behind it. Knowing how
it (could) be implemented always helps me understand things.
On 10/20/07, Jules Bean
Quite often an explicit ADT is much nicer. But they represent two opposing patterns of code-writing. Explicit ADT allows you to write case statements handling 'all the logic in one place'; a class forces you to separate the differences into 'separate instances'.
Nice ADT example. Indeed that would be how I'd do it in SML. Use a record type holding closures referencing an object of unknown type. The nice thing I've found about doing it in SML this way is that I can extract the object back out, using exceptions. e.g. (* Start Standard ML *) datatype Renderable = Renderable { render : unit -> RenderedImage, extract : unit -> unit, tag : exn } local datatype Point = Point Something exception ExtractMe Point exception Tag in fun mkPoint Something = let val p = Point Something in { render = fn () => ... , extract = fn () => raise ExtractMe p, tag = Tag } end (* extractPoint would return the Point hidden away in a Renderable. *) fun extractPoint (Renderable { tag = Tag, extract, ... }) = (extract (); Point SomethingPointless) handle ExtractMe p => p end (* End SML *) I don't know if this would work in Haskell, as I'm not familiar with Haskell exceptions. Anyway I see that Haskell has a Dynamic type... I've got a good grip on this now, I think. Thanks everyone. TJ