From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Original-To: caml-list@sympa.inria.fr Delivered-To: caml-list@sympa.inria.fr Received: from mail3-relais-sop.national.inria.fr (mail3-relais-sop.national.inria.fr [192.134.164.104]) by sympa.inria.fr (Postfix) with ESMTPS id A4B687EE51 for ; Thu, 4 Apr 2013 20:48:09 +0200 (CEST) Received-SPF: None (mail3-smtp-sop.national.inria.fr: no sender authenticity information available from domain of anthony.tavener@gmail.com) identity=pra; client-ip=209.85.215.178; receiver=mail3-smtp-sop.national.inria.fr; envelope-from="anthony.tavener@gmail.com"; x-sender="anthony.tavener@gmail.com"; x-conformance=sidf_compatible Received-SPF: Pass (mail3-smtp-sop.national.inria.fr: domain of anthony.tavener@gmail.com designates 209.85.215.178 as permitted sender) identity=mailfrom; client-ip=209.85.215.178; receiver=mail3-smtp-sop.national.inria.fr; envelope-from="anthony.tavener@gmail.com"; x-sender="anthony.tavener@gmail.com"; x-conformance=sidf_compatible; x-record-type="v=spf1" Received-SPF: None (mail3-smtp-sop.national.inria.fr: no sender authenticity information available from domain of postmaster@mail-ea0-f178.google.com) identity=helo; client-ip=209.85.215.178; receiver=mail3-smtp-sop.national.inria.fr; envelope-from="anthony.tavener@gmail.com"; x-sender="postmaster@mail-ea0-f178.google.com"; x-conformance=sidf_compatible X-IronPort-Anti-Spam-Filtered: true X-IronPort-Anti-Spam-Result: AokCAMvJXVHRVdeyk2dsb2JhbAA5CoM8uFQBiDJ9CBYOAQEBAQcLCwkUBCSCHwEBBAEnGQEbHQEDAQsGBQsDCi4hAQERAQUBHAYTG4dmAQMJBgyjJowvgnuEWQoZJw1ZiHwBBQyMPYEWBIE4B4NAA4h8jBKBYIEgilKDORYphE0dgS4 X-IPAS-Result: AokCAMvJXVHRVdeyk2dsb2JhbAA5CoM8uFQBiDJ9CBYOAQEBAQcLCwkUBCSCHwEBBAEnGQEbHQEDAQsGBQsDCi4hAQERAQUBHAYTG4dmAQMJBgyjJowvgnuEWQoZJw1ZiHwBBQyMPYEWBIE4B4NAA4h8jBKBYIEgilKDORYphE0dgS4 X-IronPort-AV: E=Sophos;i="4.87,410,1363129200"; d="scan'208";a="9825561" Received: from mail-ea0-f178.google.com ([209.85.215.178]) by mail3-smtp-sop.national.inria.fr with ESMTP/TLS/RC4-SHA; 04 Apr 2013 20:48:08 +0200 Received: by mail-ea0-f178.google.com with SMTP id o10so1140878eaj.23 for ; Thu, 04 Apr 2013 11:48:08 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=mime-version:x-received:in-reply-to:references:date:message-id :subject:from:to:cc:content-type; bh=YsaQ5SNJ2ZhMwtKzZAMxUgV1xGYodjB8aXyHXJGHtGc=; b=zPb+2CFHh+TOOM3OJRPptCUgq1RZkE2aO48OkbTU2L5j202OH2olbbjr5Qn4IiO6xq qdCwpVz2osCT1xkNdHEF7LRqFHagVx0OCmBfMoscEA6k8uUHAOKwwXBFqTCGhBAFcrbm 3GvndHynxFLavITq0lkkC3YOOBo02/036MlqqB2S2RaNgewRGsvZQZvOWu9OlrBkizWd 5CyqI/70CXIfoG2ly2ekFwzBMMUKylkW6d4pMw5QWBj46iiiKI3wZKKBPD64X6IAqrGt v/CMdizq/yHlSsqekaNaS8CKcktqv3p0nLNBiOFObf0CbS6zKMrnZ9Q2LpRhv7/2+leC MKyQ== MIME-Version: 1.0 X-Received: by 10.14.5.6 with SMTP id 6mr12957910eek.42.1365101287756; Thu, 04 Apr 2013 11:48:07 -0700 (PDT) Received: by 10.14.2.198 with HTTP; Thu, 4 Apr 2013 11:48:07 -0700 (PDT) In-Reply-To: References: Date: Thu, 4 Apr 2013 12:48:07 -0600 Message-ID: From: Anthony Tavener To: David House Cc: "caml-list@inria.fr" Content-Type: multipart/alternative; boundary=047d7b67098f56fc6004d98d6934 Subject: Re: [Caml-list] Heterogeneous dictionary --047d7b67098f56fc6004d98d6934 Content-Type: text/plain; charset=windows-1252 Content-Transfer-Encoding: quoted-printable The problem here... module Keys : sig val recovery : int Univ_map.Key.t val resist_pain : float Univ_map.Key.t ... Would be that Keys would now have dependence on types spanning the codebase. Say these modifiers use Wounds.t, Fatigue.t, Ability.Score.t, ... There are a lot of types, which mostly have a limited scope (their own module and a few others). Wouldn't it be a problem to have all types brought into this one module, which every other module also becomes dependent on? Maybe it just feels like a problem but it's just an aesthetic -- Would you do this? A few hundred keys involving types from half the modules of the codebase? I'm trying to use these "modifiers" for code organisation -- declaring snippets of functionality (all of signature 'a -> 'a... to return modified input) in a lightweight manner, which can be applied elsewhere. For example, the Virtue module can add a lot of modifers to an entity (UID). Say one entity has virtues of Agility, Inspirational, and Sun-cyclic Magic, which each adding a few modifier functions keyed to various contexts (sun-cyclic magic: "Casting" is +3 while the sun is up). The associated modifiers would be picked up in code spread throughout the application. Rules for combat, spellcasting, even character dialog... Rather than having character dialog checking for "does he have this virtue, or that one? How about this ability? Spell-effects? Reputations? ..." I want to apply all appropriate/active modifiers for entity and situation which come from other rules. So, dialog code might have a current_value, then... eg. let modified_value =3D apply_modifiers_for_context entity `CharmRoll current_value There is a lot of work on my project which I've been avoiding because the direct approach is building hairy nests of checks which call out to code everywhere... effectively splitting logic between the point of origin of a rule, and the point of application of it. I'd rather declare the individual rules, each in one piece, and "magically" apply the aggregate of rules. In a way, what I'm looking for is having a grand-central lookup, which *trusts* that I'm using the right keys at the right time (where the keys are purely symbolic with no type info)... but it would be nice if once the whole program is compiled it could identify whether that trust was broken afterall. A bit of a pipe-dream, and maybe even flawed logic. :) It might sound like I'm being too picky or even whiney... that declaring keys throughout the code is unacceptable, or having a file dependent on all types is problematic... maybe I am? The first seems disorganised and adds a mental burden to deciding and knowing where keys live; the second is a problem, isn't it? Dynamic languages can do what I want at the cost of typesafety. So I might just prefer to make that same tradeoff for one mechanism in my code... "famous last words"? I hope not. I hope it just works and I don't have nightmares about lurking segfaults. :) On Thu, Apr 4, 2013 at 3:04 AM, David House wrote: > I don't quite understand the problem. Here's an example of how one > might use univ_map: > > open Core.Std > > module Keys : sig > val recovery : int Univ_map.Key.t > val resist_pain : float Univ_map.Key.t > end =3D struct > let recovery =3D Univ_key.Key.create "recovery" Int.sexp_of_t > let resist_pain =3D Univ_key.Key.create "resist_pain" Float.sexp_of_t > end > > (In practice this might be two files: keys.ml with the implementation > and keys.mli with the signature.) You can then add things as follows: > > let add map ~key ~data =3D Univ_map.add_exn map key data in > let map =3D > Univ_map.empty > |> add ~key:Keys.recovery ~data:4 > |> add ~key:Keys.resist_pain ~data:10. > in > ... > > On 4 April 2013 09:37, Anthony Tavener wrote: > > Thank-you for the advice and pointers, folks... > > > > Well, the common problem is still the same one I've been struggling wit= h: > > "creating keys", and having to access them. > > > > I can't create keys "type-free" in a common module. As I figured... > having > > "modifier.ml" with a bunch of Key.create will have monomorphic types > which > > can't be resolved since with no usage in that module to make the type > > concrete. I had a nagging feeling I'd need a "whole-program" compiler... > > > > Instead I'd have to create keys in modules where they are used... but > then I > > might have a mess of keys like Wounds.recovery, Combat.resist_pain, ... > the > > problem being that only a fraction of these keys actually make sense > being > > associated to a particular module, and it gets confusing to know which > (of > > several candidates) I decided to stash them into. This was the > attraction to > > polymorphic variants (which I rarely use) -- they give a pre-ordained > unique > > ID based on a simple name... no declaration, and no module prefixing, > which > > seems important to me for this case. > > > > Note that I have a "database" of tables with different types > (implemented by > > first-class modules!), and it works great for the bulk of my game-state, > but > > each table is well-populated and heavily used in consistent manner. The= se > > modifiers though... they're a bit like ad-hoc message passing, where I > can > > submit any message and anywhere else add a snippet of code to interpret > it > > (not that I have any of that going on, otherwise it might hold the > > solution!). > > > > > > > > On Thu, Apr 4, 2013 at 1:38 AM, Rapha=EBl Proust > wrote: > >> > >> On Thu, Apr 4, 2013 at 1:45 AM, Anthony Tavener > >> wrote: > >> > [=85] > >> > >> And yet-another-solution, Ocsigen's Polytable: > >> http://ocsigen.org/ocsigenserver/api/Polytables > >> > >> > >> Cheers, > >> -- > >> ______________ > >> Rapha=EBl Proust > > > > > --047d7b67098f56fc6004d98d6934 Content-Type: text/html; charset=windows-1252 Content-Transfer-Encoding: quoted-printable
The problem here...

=A0 modu= le Keys : sig
=A0 =A0 val recovery : int Univ_map.Key.t
=A0 =A0 val resist_pain : float =A0Univ_map.Key.t
=A0 =A0 ...

Would be that Keys would now have dependence on types spanning the cod= ebase.

Say these modifiers use Wounds.t, Fatigue.t= , Ability.Score.t, ... There are a
lot of types, which mostly hav= e a limited scope (their own module and a few
others). Wouldn't it be a problem to have all types brought into t= his one
module, which every other module also becomes dependent o= n? Maybe it just
feels like a problem but it's just an aesthe= tic -- Would you do this? A few
hundred keys involving types from half the modules of the codebase?


I'm trying to use these &quo= t;modifiers" for code organisation -- declaring
snippets of = functionality (all of signature 'a -> 'a... to return modified
input) in a lightweight manner, which can be applied elsewhere.
<= div>
For example, the Virtue module can add a lot of modifers= to an entity (UID).
Say one entity has virtues of Agility, Inspi= rational, and Sun-cyclic Magic,
which each adding a few modifier functions keyed to various contexts
(sun-cyclic magic: "Casting" is +3 while the sun is up).= The associated
modifiers would be picked up in code spread throu= ghout the application. Rules
for combat, spellcasting, even character dialog...

Rather than having character dialog checking for "does he have t= his virtue, or
that one? How about this ability? Spell-effects? R= eputations? ..." I want to
apply all appropriate/active modifiers for entity and situation which = come
from other rules. So, dialog code might have a current_value= , then...
eg.
=A0 let modified_value =3D apply_modifier= s_for_context entity `CharmRoll current_value

There is a lot of work on my project which I've bee= n avoiding because the
direct approach is building hairy nests of= checks which call out to code
everywhere... effectively splittin= g logic between the point of origin of a
rule, and the point of application of it. I'd rather declare the i= ndividual
rules, each in one piece, and "magically" app= ly the aggregate of rules.


In a way, what I'm looking for is having a grand-central lookup, w= hich
*trusts* that I'm using the right keys at the right time= (where the keys are
purely symbolic with no type info)... but it= would be nice if once the whole
program is compiled it could identify whether that trust was broken af= terall.
A bit of a pipe-dream, and maybe even flawed logic. :)

It might sound like I'm being too picky or even = whiney... that declaring keys
throughout the code is unacceptable, or having a file dependent on all= types
is problematic... maybe I am? The first seems disorganised= and adds a
mental burden to deciding and knowing where key= s live; the second is a
problem, isn't it?

Dynamic language= s can do what I want at the cost of typesafety. So I might
just p= refer to make that same tradeoff for one mechanism in my code... "famo= us
last words"? I hope not. I hope it just works and I don't hav= e nightmares
about lurking segfaults. :)


On Thu, Apr 4, 2013 = at 3:04 AM, David House <dhouse@janestreet.com> wrote:
I don't quite understand the problem. He= re's an example of how one
might use univ_map:

open Core.Std

module Keys : sig
=A0 val recovery : int Univ_map.Key.t
=A0 val resist_pain : float =A0Univ_map.Key.t
end =3D struct
=A0 let recovery =3D Univ_key.Key.create "recovery" Int.sexp_of_t=
=A0 let resist_pain =3D Univ_key.Key.create "resist_pain" Float.s= exp_of_t
end

(In practice this might be two files: keys.ml with the implementation
and keys.mli with the signature.) You can then add things as follows:

let add map ~key ~data =3D Univ_map.add_exn map key data in
let map =3D
=A0 Univ_map.empty
=A0 |> add ~key:Keys.recovery ~data:4
=A0 |> add ~key:Keys.resist_pain ~data:10.
in
...

On 4 April 2013 09:37, Anthony Tavener <anthony.tavener@gmail.com> wrote:
> Thank-you for the advice and pointers, folks...
>
> Well, the common problem is still the same one I've been strugglin= g with:
> "creating keys", and having to access them.
>
> I can't create keys "type-free" in a common module. As I= figured... having
> "modifier.ml= " with a bunch of Key.create will have monomorphic types which
> can't be resolved since with no usage in that module to make the t= ype
> concrete. I had a nagging feeling I'd need a "whole-program&q= uot; compiler...
>
> Instead I'd have to create keys in modules where they are used... = but then I
> might have a mess of keys like Wounds.recovery, Combat.resist_pain, ..= . the
> problem being that only a fraction of these keys actually make sense b= eing
> associated to a particular module, and it gets confusing to know which= (of
> several candidates) I decided to stash them into. This was the attract= ion to
> polymorphic variants (which I rarely use) -- they give a pre-ordained = unique
> ID based on a simple name... no declaration, and no module prefixing, = which
> seems important to me for this case.
>
> Note that I have a "database" of tables with different types= (implemented by
> first-class modules!), and it works great for the bulk of my game-stat= e, but
> each table is well-populated and heavily used in consistent manner. Th= ese
> modifiers though... they're a bit like ad-hoc message passing, whe= re I can
> submit any message and anywhere else add a snippet of code to interpre= t it
> (not that I have any of that going on, otherwise it might hold the
> solution!).
>
>
>
> On Thu, Apr 4, 2013 at 1:38 AM, Rapha=EBl Proust <raphlalou@gmail.com> wrote:
>>
>> On Thu, Apr 4, 2013 at 1:45 AM, Anthony Tavener
>> <anthony.tavener@g= mail.com> wrote:
>> > [=85]
>>
>> And yet-another-solution, Ocsigen's Polytable:
>> http://ocsigen.org/ocsigenserver/api/Polytables
>>
>>
>> Cheers,
>> --
>> ______________
>> Rapha=EBl Proust
>
>

--047d7b67098f56fc6004d98d6934--