From: Leo White <lpw25@cam.ac.uk>
To: Roberto Di Cosmo <roberto@dicosmo.org>
Cc: caml-list@inria.fr
Subject: Re: [Caml-list] Adding Dimensions to types
Date: Fri, 13 Jun 2014 10:52:23 +0100 [thread overview]
Message-ID: <868up1kug8.fsf@cam.ac.uk> (raw)
In-Reply-To: <CAJBwKuWZHefK-_hD7TdOxKFK8YFU06NXjn2UZSgu6O_5aXVcHQ@mail.gmail.com> (Roberto Di Cosmo's message of "Fri, 13 Jun 2014 11:10:24 +0200")
> Now the question that arose yesterday, and that we could not answer right away, is whether it is possible to encode
> such dymension checking in OCaml today using only the existing type-system features, so I am passing it over to the
> list :-)
You can do something reasonable using difference lists to encode a
dimension in a phantom type. For example, the following module (based on
an initial version by Stephen Dolan):
module Unit : sig
type +'a suc
type (+'a, +'b) quantity
val of_float : float -> ('a, 'a) quantity
val metre : ('a, 'a suc) quantity
val mul : ('a, 'b) quantity -> ('b, 'c) quantity -> ('a, 'c) quantity
val add : ('a, 'b) quantity -> ('a, 'b) quantity -> ('a, 'b) quantity
val neg : ('a, 'b) quantity -> ('a, 'b) quantity
val inv : ('a, 'b) quantity -> ('b, 'a) quantity
end = struct
type 'a suc = unit
type ('a, 'b) quantity = float
let of_float x = x
let metre = 1.
let mul x y = x *. y
let add x y = x +. y
let neg x = 0. -. x
let inv x = 1. /. x
end
This successfully tracks the dimension of quatities:
# open Unit;;
# let m10 = mul (of_float 10.) metre;;
val m10 : ('a, 'a Unit.suc) Unit.quantity = <abstr>
# let sum = add m10 m10;;
val sum : ('a, 'a Unit.suc) Unit.quantity = <abstr>
# let sq = mul m10 m10;;
val sq : ('a, 'a Unit.suc Unit.suc) Unit.quantity = <abstr>
# let cube = mul m10 (mul m10 m10);;
val cube : ('a, 'a Unit.suc Unit.suc Unit.suc) Unit.quantity = <abstr>
# let _ = add (mul sq (inv cube)) (inv m10);;
- : ('a Unit.suc, 'a) Unit.quantity = <abstr>
and it will give errors if they are used incorrectly:
# let _ = add sq cube;;
Characters 15-19:
let _ = add sq cube;;
^^^^
Error: This expression has type
('a, 'a Unit.suc Unit.suc Unit.suc) Unit.quantity
but an expression was expected of type
('a, 'a Unit.suc Unit.suc) Unit.quantity
The type variable 'a occurs inside 'a Unit.suc
# let _ = add m10 (mul m10 m10);;
Characters 16-29:
let _ = add m10 (mul m10 m10);;
^^^^^^^^^^^^^
Error: This expression has type ('a, 'a Unit.suc Unit.suc) Unit.quantity
but an expression was expected of type ('a, 'a Unit.suc) Unit.quantity
The type variable 'a occurs inside 'a Unit.suc
However, it will infer too restrictive types for some things:
# let sq x = mul x x;;
val sq : ('a, 'a) Unit.quantity -> ('a, 'a) Unit.quantity = <fun>
The "real" type of `sq` requires higher-kinded and higher-rank
polymorphism. Using functors you can encode `sq` thus:
# module Sq (X : sig type 'a t end) = struct
type arg = {x: 'a. ('a, 'a X.t) quantity}
let sq {x} = mul x x
end;;
and apply it like so:
# module AppSq = Sq(struct type 'a t = 'a suc end);;
# let x = AppSq.sq {AppSq.x = m10};;
val x : ('a, 'a Unit.suc Unit.suc) Unit.quantity = <abstr>
It is also worth noting that -rectypes breaks this encoding:
#rectypes;;
# let _ = add sq cube;;
- : ('a Unit.suc as 'a, 'a Unit.suc Unit.suc) Unit.quantity = <abstr>
Regards,
Leo
next prev parent reply other threads:[~2014-06-13 9:52 UTC|newest]
Thread overview: 10+ messages / expand[flat|nested] mbox.gz Atom feed top
2014-06-13 9:10 Roberto Di Cosmo
2014-06-13 9:42 ` David MENTRE
2014-06-13 10:09 ` Roberto Di Cosmo
2014-06-13 9:43 ` Gabriel Scherer
2014-06-13 9:54 ` Roberto Di Cosmo
2014-06-13 12:10 ` Nicolas Boulay
2014-06-13 9:52 ` Leo White [this message]
2014-06-13 10:12 ` Roberto Di Cosmo
2014-06-13 11:06 ` Leo White
2014-06-13 20:08 ` Török Edwin
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=868up1kug8.fsf@cam.ac.uk \
--to=lpw25@cam.ac.uk \
--cc=caml-list@inria.fr \
--cc=roberto@dicosmo.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox