[Haskell-cafe] Strong duck typing / structural subtyping / type class aliases / ??? in Haskell

2009-09-29 Thread oleg

Alp Mestan wrote:
 Indeed, OCaml has stuctural polymorphism, it's a wonderful feature.

 *# let f myobj = myobj#foo Hi !;;
 val f :  foo : string - 'a; ..  - 'a = fun*

And Haskell has that too:

 -- This is how we define labels.
 data Field1 deriving Typeable; field1 = proxy::Proxy Field1

 -- This is how record selection looks like.
 foo f = f # field1

The inferred type of  foo is

*OCamlTutorial :t foo
foo :: (HasField (Proxy Field1) r v) = r - v

It doesn't seem too different from the OCaml's type; the type variable
r acts as a row type.

The quoted example is the first from many others described in
http://darcs.haskell.org/OOHaskell/OCamlTutorial.hs

The file quotes at length OCaml's Object tutorial and then
demonstrates how the OCaml code can be written in Haskell.  When it
comes to objects, structural subtyping, width and depth subtyping,
etc., Haskell does not seem to miss match compared to OCaml. In
contrast, Haskell has a few advantages when it comes to coercions
(one does not have to specify the type to coerce to, as Haskell can
figure that out). The other files in that directory give many more
example of encoding C++, Eiffel, OCaml patterns.

___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


[Haskell-cafe] Strong duck typing / structural subtyping / type class aliases / ??? in Haskell

2009-09-25 Thread Peter Verswyvelen
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
suggestedhttp://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
___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


Re: [Haskell-cafe] Strong duck typing / structural subtyping / type class aliases / ??? in Haskell

2009-09-25 Thread Job Vranish
Short answer: There is no good way of doing what you want.
This is actually one of my biggest annoyances with haskell (right up there
with disallowing infinite types). They are many techniques that work better
or worse depending on the application, but non are very satisfactory IMO.
Your typeclass solution(or some variant of) is pretty much your best option.
If you're careful about how you define your datatype and classes you can
avoid the type families and such, but the whole point is to not have to be
careful.
If your types are fixed (which is usually true as long as you're not using
existentials) you might be able to get away with using
-XDisambiguateFieldRecords

If you want anything better you're probably going to have to use some form
of preprocessor (like OHaskell).


Supposedly OCaml has an OO feature that does this but I haven't tried it
out.

I would suspect that the reason why haskell doesn't provide duck typeing on
record fields is that analisys for optimizations is much more complicated
(as it currently stands, records are nothing but sugar on top of algeraic
datatypes).
You can end up with all sorts of weird things with duck typeing on record
fields, like unnamed datatypes. For example:

(using class constraint style to inidicate a record field restriction for
lack of a better syntax)
setPosition :: (position a) =Vector - a - a
setPosition v x = x { position = v }

translate :: (position a) =Vector - a - a
translate v x = x { position = v + (position x) }

getPosition :: (position a) = a - Vector
getPosition x = position x

result :: Vector
result = getPosition $ translate someVector $ setPosition someOtherVector

The type variable 'a' in these functions is never fixed to a specific type,
and it actually doesn't need to be. The compiler would just have to invent a
suitable one (a type with only the field 'position' of type Vector).

Maybe someday haskell will finially implement good, clean, duck typeable,
record functionality. I will be waiting...

- Job


On Fri, Sep 25, 2009 at 9:54 AM, Peter Verswyvelen bugf...@gmail.comwrote:

 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 
 suggestedhttp://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 

Re: [Haskell-cafe] Strong duck typing / structural subtyping / type class aliases / ??? in Haskell

2009-09-25 Thread Alp Mestan
On Fri, Sep 25, 2009 at 8:14 PM, Job Vranish jvran...@gmail.com wrote:

 Supposedly OCaml has an OO feature that does this but I haven't tried it
 out.


Indeed, OCaml has stuctural polymorphism, it's a wonderful feature.

*# let f myobj = myobj#foo Hi !;;
val f :  foo : string - 'a; ..  - 'a = fun*

IIRC, there has been work on Template Haskell for structural polymorphism.

-- 
Alp Mestan
http://blog.mestan.fr/
http://alp.developpez.com/
___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


Re: [Haskell-cafe] Strong duck typing / structural subtyping / type class aliases / ??? in Haskell

2009-09-25 Thread Casey Hawthorne
On Fri, 25 Sep 2009 23:25:21 +0200, you wrote:

On Fri, Sep 25, 2009 at 8:14 PM, Job Vranish jvran...@gmail.com wrote:

 Supposedly OCaml has an OO feature that does this but I haven't tried it
 out.


Indeed, OCaml has stuctural polymorphism, it's a wonderful feature.

*# let f myobj = myobj#foo Hi !;;
val f :  foo : string - 'a; ..  - 'a = fun*

IIRC, there has been work on Template Haskell for structural polymorphism.

Structural subtyping/polymorphism:

Pros:
- an object can be coerced to any compatible type, the types do not
have to be specified ahead of time, that is at compile time.

Cons:
- may be overly permissive; some coercions might not make sense
semantically.

I wonder how Haskell will minimize the cons, since it is strongly
typed.

--
Regards,
Casey
___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


Re: [Haskell-cafe] Strong duck typing / structural subtyping / type class aliases / ??? in Haskell

2009-09-25 Thread Casey Hawthorne
On Fri, 25 Sep 2009 23:25:21 +0200, you wrote:

On Fri, Sep 25, 2009 at 8:14 PM, Job Vranish jvran...@gmail.com wrote:

 Supposedly OCaml has an OO feature that does this but I haven't tried it
 out.


Indeed, OCaml has stuctural polymorphism, it's a wonderful feature.

*# let f myobj = myobj#foo Hi !;;
val f :  foo : string - 'a; ..  - 'a = fun*

IIRC, there has been work on Template Haskell for structural polymorphism.

Structural subtyping/polymorphism:

Pros:
- an object can be coerced to any compatible type, the types do not
have to be specified ahead of time, that is at compile time.

Cons:
- may be overly permissive; some coercions might not make sense
semantically.

I wonder how Haskell will minimize the cons, since it is strongly
typed.


I forgot to add: that even if strong typing could be measured on sum
numerical scale, I don't know whether Haskell has a higher
measure/metric than OCaml, in the strong typing area.

--
Regards,
Casey
___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


Re: [Haskell-cafe] Strong duck typing / structural subtyping / type class aliases / ??? in Haskell

2009-09-25 Thread wren ng thornton

Peter Verswyvelen wrote:

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)


The common name for (one form of) what you're seeking is row polymorphism:

  http://www.cs.cmu.edu/~neelk/rows.pdf

This is implemented in OCaml but, like most OO features in functional 
languages, it is often ignored or forgotten about. As others've 
mentioned, there are some cases where row polymorphism is really nice, 
but it's not always semantically coherent.


--
Live well,
~wren
___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


Re: [Haskell-cafe] Strong duck typing / structural subtyping / type class aliases / ??? in Haskell

2009-09-25 Thread Sebastian Sylvan
On Fri, Sep 25, 2009 at 10:55 PM, Casey Hawthorne cas...@istar.ca wrote:

 On Fri, 25 Sep 2009 23:25:21 +0200, you wrote:

 On Fri, Sep 25, 2009 at 8:14 PM, Job Vranish jvran...@gmail.com wrote:
 
  Supposedly OCaml has an OO feature that does this but I haven't tried it
  out.
 
 
 Indeed, OCaml has stuctural polymorphism, it's a wonderful feature.
 
 *# let f myobj = myobj#foo Hi !;;
 val f :  foo : string - 'a; ..  - 'a = fun*
 
 IIRC, there has been work on Template Haskell for structural polymorphism.

 Structural subtyping/polymorphism:

 Pros:
 - an object can be coerced to any compatible type, the types do not
 have to be specified ahead of time, that is at compile time.

 Cons:
 - may be overly permissive; some coercions might not make sense
 semantically.

 I wonder how Haskell will minimize the cons, since it is strongly
 typed.


I kind of think there's no real problem here. If you say that you can accept
any record with a given set of fields, then you have to make sure you make
no other assumptions. This is, in principle, no different from passing a
speed Double to a function that expects a mass Double (e.g. it may produce
garbage for negative values). In both cases a function that requires extra
invariants can enforce it by using a newtype that's constructed and
manipulated in a way which preserves the extra semantic rules.

-- 
Sebastian Sylvan
___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe