Version française
Home     About     Download     Resources     Contact us    
Browse thread
Re: [Caml-list] Improving OCaml's choice of type to display
[ Home ] [ Index: by date | by threads ]
[ Search: ]

[ Message by date: previous | next ] [ Message in thread: previous | next ] [ Thread: previous | next ]
Date: -- (:)
From: Damien Guichard <alphablock@o...>
Subject: Re: [Caml-list] Improving OCaml's choice of type to display

> If you have a design approach that simultaneously makes good use of functors,
> modules and signatures and makes OCaml's type-to-display-selector happy, I'd be very interested in hearing it.

Indeed, good use of functors, modules and signatures doesn't come without type verbosity.
I have also faced it, it's a real concern.
The Core user or library user has to be tolerant, not every type can be called t, not every module can be called M, modules have to include further modules, as a result type paths become longer.
Plus functors add module as parameters and as a result types become more difficult to interpret.
Main part of the answer lies in accepting the cultural shock.
More capable code libraries come with a steepier learning curve, both as a user and as an implementer.  

> To be clear, some of this stuff can be made better by using signature functors, but that has its own problems in terms of messiness and
> boilerplate.

Ocaml-Idaho signatures are done by composing more elementary module types.
As a result the design is highly modular but you end up with more boilerplate and type equalities.
However type equalities have a good reason, they capture the context.
The context is more important than what the actual type is.

May be the toplevel could be more aware of opened modules then your example would be rendered as : 

# open Option.Monad_infix;;
# Map.find m 3 >>| fun x -> x + 1;;
- : int monad = Some 4

That would be much shorter without erasing type equalities.
 
- damien


PS:

As a module design example here is an excerpt of the OCaml-Idaho UnbalancedMap module, which has both a Mutable and a Pure version implemented as recursive modules. On one hand it's pure boilerplate, on the other hand it's just plain usage of ML modules.


module rec Mutable 
  :
  functor (Ord: Interfaces.Ordered) ->  
  sig
    include Interfaces.MutableMap
       with type key = Ord.ordered
    include Interfaces.MutableKeySet
       with type 'a set = 'a map and type set_key = key
    include Interfaces.OrderedKeyFoldable
       with type 'a foldable = 'a map and type fold_key = key
    val inserted:  key -> 'a -> 'a map -> bool
    val root_inserted: key -> 'a -> 'a map -> bool
    val flatten_map: (key -> 'a -> 'a map) -> 'a map -> 'a map
    val to_pure: 'a map -> 'a Pure(Ord).map
    val to_pure_unsafe: 'a map -> 'a Pure(Ord).map
  end  
  =
  functor (Ord: Interfaces.Ordered) ->
  struct
  
    include BinaryTree_Keyed.Make(Ord)

    module Order = Ord
     
    type 'a map = 'a tree ref
    type 'a foldable = 'a map and fold_key = key
    type ('a,'b) fold  = (key -> 'a -> 'b -> 'b) -> 'b -> 'a map -> 'b

    type 'a set = 'a map
    type set_key = key
    type 'a set_select = 'a select

    ...
    
  end
  
and Pure
  :
  functor (Ord: Interfaces.Ordered) ->
  sig
    include Interfaces.PureMap
       with type key = Ord.ordered
    include Interfaces.PureKeySet
       with type 'a set = 'a map and type set_key = key
    include Interfaces.OrderedKeyFoldable
       with type 'a foldable = 'a map and type fold_key = key
    val root_add:     key -> 'a -> 'a map -> 'a map
    val splay_add:    key -> 'a -> 'a map -> 'a map
    val splay_lookup: key -> 'a map -> 'a map * 'a option
    val splay_find:   key -> 'a map -> 'a map * 'a
    val flatten_map: (key -> 'a -> 'a map) -> 'a map -> 'a map
    val to_mutable: 'a map -> 'a Mutable(Ord).map
    val to_mutable_unsafe: 'a map -> 'a Mutable(Ord).map
  end
  =
  functor (Ord: Interfaces.Ordered) ->
  struct
  
    include BinaryTree_Keyed.Make(Ord)

    module Order = Ord
     
    type 'a map = 'a tree
    type 'a foldable = 'a map and fold_key = key
    type ('a,'b) fold  = (key -> 'a -> 'b -> 'b) -> 'b -> 'a map -> 'b

    type 'a set = 'a map
    type set_key = key
    type 'a set_select = 'a select
    
    ...

  end





En réponse au message
de : Yaron Minsky
du : 2009-10-09 18:52:40
À : Damien Guichard
CC : caml-list@yquem.inria.fr
Sujet : Re: [Caml-list] Improving OCaml's choice of type to display

I do basically think of this as a deficiency in the compiler as opposed to a deficiency in core (although it's hardly a major deficiency in the compiler).  Signatures, modules and functors are an important part of the language, and if you want to use them in a significant way, then you will end up having multiple paths to get to the same type.  OCaml's algorithm for choosing the type to display is somewhat unfortunate in this regard.

If you have a design approach that simultaneously makes good use of functors, modules and signatures and makes OCaml's type-to-display-selector happy, I'd be very interested in hearing it.

Finally, the specific point you make argues against the specific heuristic (smallest type name) I proposed, but not against all other heuristics.  Another heuristic which I think has some potential is choosing the type name with the smallest number of dots.  (also, as a matter of personal preference, in the case that you outline, I would prefer the answer of "int" to "color", but that is just a coincidence, of course.)

To be clear, some of this stuff can be made better by using signature functors, but that has its own problems in terms of messiness and boilerplate.  That said, I have half a mind to write a syntax extension to clean that up, and switch over to signature functors, for this and other reasons.  That said, signature functors only clean up a little bit of the problem.

y

On Fri, Oct 9, 2009 at 10:18 AM, Damien Guichard <alphablock@orange.fr> wrote:


Hi Yaron,

I think you better think twice about the problem in general (rather than the particular needs of Core) before proposing some controversial type display improvement.

Imagine my code is:

  type color = int 

  let black : color = 0 

Then, following your proposition, evaluating black should give me an int rather than a color because int is shorter and therefore nicer.

So, now, what's the point in the color type declaration ?
There is none, type aliasing becomes useless because you can't expose it.
Call me crazy but i whish i can use more than 3 characters as a type name. 

So you want it to be displayed as an Int.t rather than an Int.comparable ?
Then just declare it as Int.t rather than Int.comparable, or choose another shorter name, it's not an OCaml issue, its' a Core issue.
(obviously it would really help if no english word would be more than 6 characters but Ocaml can't be blamed for that)

I mean, when designing an elaborate software library, you have to make choices, and often, no matter how good OCaml is, some choices will be compromises. You have to pick the lesser between several evils and live with it.

I have learned that when programming Ocaml-Idaho, suddenly module names become longer, module types become more composited, data types become more subtle, and so on and so on...

Blaming OCaml is a too easy path.

At one certain point you have to face the verbosity you have created and decide whether the additionnal expressivity worths the price.
If you think it does then it's ok, if not then just amend, if amending doesn't help then consider refactoring.
Seek the best expressiveness/verbosity ratio without sacrifying too much functionality.
That's your job as a library designer.


- damien





En réponse au message
de : Yaron Minsky
du : 2009-10-09 11:58:11
À : Andrej Bauer
CC : caml-list@yquem.inria.fr
Sujet : Re: [Caml-list] Improving OCaml's choice of type to display

Well, if we're picking heuristics, the fewest number of characters wouldn't be crazy either.  Given the choice between Int.t and Int.comparable (which are aliases for the same type), I'd prefer to see Int.t.

y


On Fri, Oct 9, 2009 at 3:33 AM, Andrej Bauer <andrej.bauer@andrej.com> wrote:

On Fri, Oct 9, 2009 at 3:40 AM, Yaron Minsky <yminsky@gmail.com> wrote:
> Choosing shorter names.

By which you probably mean "the fewest number of dots (module
projections)". It might be a bit annoying if the code that prints
doesn't know what modules are open. What do the INRIA priests say?

Andrej




_______________________________________________
Caml-list mailing list. Subscription management:
http://yquem.inria.fr/cgi-bin/mailman/listinfo/caml-list
Archives: http://caml.inria.fr
Beginner's list: http://groups.yahoo.com/group/ocaml_beginners
Bug reports: http://caml.inria.fr/bin/caml-bugs