[Haskell-cafe] Strong duck typing / structural subtyping / type
class aliases / ??? in Haskell
Peter Verswyvelen
bugfact at gmail.com
Fri Sep 25 09:54:12 EDT 2009
Haskell's records are a bit annoying, and type-classes often group together
too many methods, which means you make early decisions about future unknown
requirements, and IMO you always get it wrong :-)
After having read an email in the cafe about the Noop language & Self
language, I realized that what I really would like to have is "strong duck
typing" on records (or is it called structural subtyping? or
prototype-based-objects? or something like that)
For example (silly example full of inaccuracies, but you get the picture):
class HasPosition a where
position :: a -> Point
withPosition :: Point -> a -> a
class HasVelocity a where
velocity :: a -> Vector
withVelocity :: Vector -> a -> a
which we really should write as
field HasPosition :: Point
field HasVelocity :: Vector
And then
record IsKinetic :: HasPosition HasVelocity
suppose we write a function like
kineticEulerStep dt k = withPosition (position k .+^ dt *^ velocity k) k
kineticEulerStep will work on any type a that HasPosition and HasVelocity,
and would get inferred signature
kineticEulerStep :: IsKinetic a => Float -> a -> a
which is identical to
kineticEulerStep :: (HasPosition a, HasVelocity a) => Float -> a -> a
So basically kineticEulerStep accepts anything that HasPosition and
HasVelocity, whatever it is.
So if it walks like a duck and ..., then it is a duck, but statically
known...
We could also do
field HasForce :: Vector
field HasMass :: Float
record IsDynamic :: IsKinetic HasForce HasMass
acceleration d = force d ^/ mass d
withAcceleration a d = withForce (a ^* mass d) d
dynamicEulerStep dt d = withVelocity (velocity d ^+^ dt *^ acceleration d)
Of course you would also need type families to be really correct since
Vector, Point, etc should also be parametrized.
And really kineticEulerStep might also work on something that HasVelocity
and HasAcceleration (since the code in dynamicEulerStep is almost the same
as kineticEulerStep), so better abstraction might be needed.
I'm not sure what kind of overhead a system like this would have in Haskell,
since I suspect the many dictionaries are often not optimized away.
I think for Haskell prime, something like this was
suggested<http://repetae.net/recent/out/classalias.html>,
but is was rejected?
Languages like OCaml and haXe <http://haxe.org/manual/2_types> also provide
a similar feature?
I would like to collect ways of doing this in Haskell, without boilerplate,
and preferably without runtime overhead.
I remember reading OOHaskell a while time ago, and while I didn't understand
a lot of it, I recall it also was doing a similar thing, but since the
compiler lacks native support, the error messages you get most likely make
it impossible to figure out what is going wrong. I think Grapefruit's
Records, HList, Data.Accessor, etc.. might also work.
Any guidelines and comments regarding "strong duck typing"/"structural
subtyping" are very welcome, since the lack of this is the only reason why I
would prefer a dynamic language over a static one.
Thanks a lot,
Peter Verswyvelen
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://www.haskell.org/pipermail/haskell-cafe/attachments/20090925/0b5a90b4/attachment.html
More information about the Haskell-Cafe
mailing list