From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: 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 617587FFE1 for ; Sat, 8 Oct 2016 23:51:38 +0200 (CEST) Authentication-Results: mail3-smtp-sop.national.inria.fr; spf=None smtp.pra=shayne.fletcher.50@gmail.com; spf=Pass smtp.mailfrom=shayne.fletcher.50@gmail.com; spf=None smtp.helo=postmaster@mail-yw0-f176.google.com Received-SPF: None (mail3-smtp-sop.national.inria.fr: no sender authenticity information available from domain of shayne.fletcher.50@gmail.com) identity=pra; client-ip=209.85.161.176; receiver=mail3-smtp-sop.national.inria.fr; envelope-from="shayne.fletcher.50@gmail.com"; x-sender="shayne.fletcher.50@gmail.com"; x-conformance=sidf_compatible Received-SPF: Pass (mail3-smtp-sop.national.inria.fr: domain of shayne.fletcher.50@gmail.com designates 209.85.161.176 as permitted sender) identity=mailfrom; client-ip=209.85.161.176; receiver=mail3-smtp-sop.national.inria.fr; envelope-from="shayne.fletcher.50@gmail.com"; x-sender="shayne.fletcher.50@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-yw0-f176.google.com) identity=helo; client-ip=209.85.161.176; receiver=mail3-smtp-sop.national.inria.fr; envelope-from="shayne.fletcher.50@gmail.com"; x-sender="postmaster@mail-yw0-f176.google.com"; x-conformance=sidf_compatible IronPort-PHdr: =?us-ascii?q?9a23=3AJejHjBLDxqsD7wp60dmcpTZWNBhigK39O0sv0rFi?= =?us-ascii?q?tYgUIvzxwZ3uMQTl6Ol3ixeRBMOAuqgC0Led6v29EUU7or+5+EgYd5JNUxJXwe?= =?us-ascii?q?43pCcHRPC/NEvgMfTxZDY7FskRHHVs/nW8LFQHUJ2mPw6anHS+4HYoFwnlMkIt?= =?us-ascii?q?f6KuS9SU1Jn8jr3vs7ToICxwzAKnZr1zKBjk5S7wjeIxxbVYF6Aq1xHSqWFJce?= =?us-ascii?q?kFjUlhJFaUggqurpzopM0r221qtvkg789NV7nhN+R9FOQATWduD2dgxsDxuBzS?= =?us-ascii?q?BTqG4n8bSi1CgxNMBw/dxB7/V5b19CD9s7wu9jOdOJjNTbklXznqwaNmVBTohT?= =?us-ascii?q?1PYyU5+XDRh4p+iK9HqxKsvVoim6bbZYiUMLx1eaaLLoBSfnZIQssED38JOYi7?= =?us-ascii?q?dYZaSrNZZes=3D?= X-IronPort-Anti-Spam-Filtered: true X-IronPort-Anti-Spam-Result: =?us-ascii?q?A0ApAAAyaflXhrChVdFdGgEBAQECAQEBA?= =?us-ascii?q?QgBAQEBFwEBBAEBCgEBgxEBAQEBAXRtDweNLJcCjEiHaYILHoYCAoFzBzgUAQE?= =?us-ascii?q?BAQEBAQEBAQESAQEBCAsLCRkvgjIEARUBBIIQAQEBAwESEQQZARsdAQMBCwYDA?= =?us-ascii?q?gsNIAoCAiEBAREBBQEcBhMiiBMBAw8IlXePTYEyPjKLQoFrgl8Fg14KGScNU4M?= =?us-ascii?q?RAQEBAQEFAQEBAQEBGQMGEIsCgkeFBIJbBYEhAY0YixArCAEBgSaLTIMLj3SIY?= =?us-ascii?q?4QUgj0THoERHoNdIIF6IjQBh0eBQQEBAQ?= X-IPAS-Result: =?us-ascii?q?A0ApAAAyaflXhrChVdFdGgEBAQECAQEBAQgBAQEBFwEBBAE?= =?us-ascii?q?BCgEBgxEBAQEBAXRtDweNLJcCjEiHaYILHoYCAoFzBzgUAQEBAQEBAQEBAQESA?= =?us-ascii?q?QEBCAsLCRkvgjIEARUBBIIQAQEBAwESEQQZARsdAQMBCwYDAgsNIAoCAiEBARE?= =?us-ascii?q?BBQEcBhMiiBMBAw8IlXePTYEyPjKLQoFrgl8Fg14KGScNU4MRAQEBAQEFAQEBA?= =?us-ascii?q?QEBGQMGEIsCgkeFBIJbBYEhAY0YixArCAEBgSaLTIMLj3SIY4QUgj0THoERHoN?= =?us-ascii?q?dIIF6IjQBh0eBQQEBAQ?= X-IronPort-AV: E=Sophos;i="5.31,462,1473112800"; d="scan'208,217";a="196100827" Received: from mail-yw0-f176.google.com ([209.85.161.176]) by mail3-smtp-sop.national.inria.fr with ESMTP/TLS/AES128-GCM-SHA256; 08 Oct 2016 23:51:36 +0200 Received: by mail-yw0-f176.google.com with SMTP id t193so51244773ywc.2 for ; Sat, 08 Oct 2016 14:51:36 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=mime-version:in-reply-to:references:from:date:message-id:subject:to :cc; bh=EcsSe3sZGG5WFPJsBm++cr+SUXEaXwxWAu+4U+qQHNU=; b=aPPALOGSsWMuvuI+3JKq+xmho/u2EnHcgu3TLZKgq5H8o+K6roDLmvXVQaSAzW0fWL 3MYY7ikcohxr4PEgqz/A0j8SKFgBGd96eh2bmAw2Bsvfi/EhMjYJ5FcHqySKhC9VoBc/ ToVhq8EnpsaxGRikzl0MnWU598cjZmHaOws8VzCAnEF5sdtX1YmkTWYMzp9WahfH8yJT +rcqefeN8HMp8VuFJKoIEKxqIXoQADUaH/uryF8kWIceB/QpXBY9c7VieYUmj10VSd30 o/bXIZoid+2tZnqgBFl9aFKhARBpLY/J61Y3xS1pASWJv+z0Pl+DrW/Yx5/w1g0JT8GK +EKQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:mime-version:in-reply-to:references:from:date :message-id:subject:to:cc; bh=EcsSe3sZGG5WFPJsBm++cr+SUXEaXwxWAu+4U+qQHNU=; b=bCEgDdYJSZcIAhpXLOWkOZXHebDCviKD/9ITq1hR20NmZOm0FgeSAhQQA1UqFbtFId ndY72+q5gVVyWNWx+w40cdbDH1ncRxGMYT2iuVT/1JOd5sNK4x4YU5LoGnot5fFrNoJJ piMStdwJQvgfV1b4U7LXZRbBhPY5sT+Y1hI8J41URO6YoC/+zC79C7SwhNL/mCGogNP1 c2GeSXroGjbayYxHpGhNuekxsJk0v534QlWLPW1sd2YaVWX51uX5Egugcu4k0fuoGMI0 PnFTokcu2JBttCnnR8+U3Z12QtKhwQ5oY3A/M5NmHvr1zHbA9wBNCK9idvjG5QcAp6mB us1A== X-Gm-Message-State: AA6/9RlVNLzmT1N+uJa4xShmmzIXSSZXKiNubKVi2lGOohzsiupZooExvLV7ZMNvYGWzsOhNAcyQnfJFzxvGsw== X-Received: by 10.129.86.4 with SMTP id k4mr20657313ywb.103.1475963495148; Sat, 08 Oct 2016 14:51:35 -0700 (PDT) MIME-Version: 1.0 Received: by 10.37.39.202 with HTTP; Sat, 8 Oct 2016 14:51:14 -0700 (PDT) In-Reply-To: References: <86a4a20a-c5de-a3b3-85c0-621f09a56b81@digirati.com.br> From: Shayne Fletcher Date: Sat, 8 Oct 2016 17:51:14 -0400 Message-ID: To: Jeremy Yallop Cc: Andre Nathan , "caml-list@inria.fr users" Content-Type: multipart/alternative; boundary=001a11432e0ad476ac053e6187cb Subject: Re: [Caml-list] Encoding "links" with the type system --001a11432e0ad476ac053e6187cb Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: quoted-printable On Fri, Oct 7, 2016 at 1:02 PM, Shayne Fletcher < shayne.fletcher.50@gmail.com> wrote: > On Wed, Sep 21, 2016 at 6:22 PM, Jeremy Yallop wrote: > >> I'll describe an interface based on these ideas that maintains the >> properties you stipulate. I'll leave the problem of building an >> implementation that satisfies the interface to you. (In fact, the >> interface is the tricky part and the implementation is straightforward >> if you can treat all the type parameters as phantom.) >> > > =E2=80=8BHow's this? > > module M : S =3D struct > ... > =E2=80=8B I've hit a problem with my attempt at an implementation actually :( The issue is, the program below as written seems to work, but, if the type [_ set] is made abstract in the signature [S], typing breaks. Can somebody explain where I'm going wrong? module type S =3D sig type _ sink type _ source type _ set =3D (string * string) list (*Why can't this be abstract?*) type ('source, 'sink) link type ('sink, 'set) accepts val mk_sink : string -> 'sink sink val mk_source : string -> 'source source val mk_link : 'source source * 'sink sink -> ('source, 'sink) link type 'sink fresh_set =3D | Fresh_set : { set : 'set set; accepts : ('sink, 'set) accepts; } -> 'sink fresh_set val create_set : 'sink sink -> 'sink fresh_set type ('sink, 'parent) augmented_set =3D | Augmented_set : { set : 'set set; accepts: ('sink, 'set) accepts; cc : 's. ('s, 'parent) accepts -> ('s, 'set) accepts } -> ('sink, 'parent) augmented_set val insert_link : ('source, 'sink) link -> 'parent set -> ('sink, 'parent) accepts -> ('source, 'parent) augmented_set end module M : S =3D struct type 'sink sink =3D { name : string } type 'source source =3D { name : string } type 'set set =3D (string * string) list type ('source, 'sink) link =3D ('source source * 'sink sink) let mk_sink (name : string) : 'sink sink =3D {name} let mk_source (name : string) : 'source source =3D {name} let mk_link ((source, sink) : 'source source * 'sink sink) : ('source, 'sink) link =3D (source, sink) type ('sink, 'set) accepts =3D | Accepts : ('sink, 'set) accepts type 'sink fresh_set =3D | Fresh_set : { set : 'set set; accepts : ('sink, 'set) accepts; } -> 'sink fresh_set let create_set (s : 'sink sink) : 'sink fresh_set =3D Fresh_set { set =3D ([] : 'set set); accepts =3D (Accepts : ('sink, 'set) accepts) } type ('sink, 'parent) augmented_set =3D | Augmented_set : { set : 't set; accepts: ('sink, 't) accepts; cc : 's. ('s, 'parent) accepts -> ('s, 't) accepts } -> ('sink, 'parent) augmented_set let insert_link (l : ('source, 'sink) link) (s : 'parent set) (a : ('sink, 'parent) accepts) : ('source, 'parent) augmented_set =3D let {name =3D src} : 'source source =3D fst l in let {name =3D dst} : 'sink sink =3D snd l in Augmented_set { set : 't set =3D (src, dst) :: s; accepts =3D (Accepts : ('source, 't) accepts); cc =3D fun (_ : (_, 'parent) accepts) -> (Accepts : (_, 'parent) accepts) } end module Test (E : S) =3D struct open E type t1 and t2 and t3 and t4 let snk1 : t1 sink =3D mk_sink "sink1" let snk2 : t2 sink =3D mk_sink "sink2" let snk3 : t4 sink =3D mk_sink "sink3" let src1 : t2 source =3D mk_source "source1" let src2 : t3 source =3D mk_source "source2" let link1 : (t2, t1) link =3D mk_link (src1, snk1) (*t2 src, t1 sink*) let link2 : (t3, t1) link =3D mk_link (src2, snk1) (*t3 src, t1 sink*) let link3 : (t3, t2) link =3D mk_link (src2, snk2) (*t3 src, t2 sink*) let link4 : (t3, t4) link =3D mk_link (src2, snk3) (*t3 src, t4 sink*) let test () =3D (*Create a fresh set from a sink of type [t1]*) let (Fresh_set {set; accepts =3D a} : t1 fresh_set) =3D create_set snk1 in (* - [a] is evidence [set] accepts links with sink type [t1] *) (*Insert a [(t2, t1) link]*) let Augmented_set {set =3D set1; accepts =3D a1; cc =3D cc1} =3D insert_link link1 set a in (* - [a1] is evidence [set1] accepts links with sink type [t2] ([t2] is the source type of [link1]) - [cc] says that [set1] accepts links with sink types that its parent [set] does: - [cc1 a] provides evidence that says that [set1] will accept [link2] which has sink type [t1] *) (*Insert a [(t3, t1)] link*) let Augmented_set {set =3D set2; accepts =3D a2; cc =3D cc2} =3D insert_link link2 set (cc1 a) in (* - [a2] says that [set2] accepts links with sink type [t3] ([t3] is the source type of [link2]) - [cc2] says that [set2] accepts links with sink types that its parent does: - [cc2 a1] provides evidence that says that [set2] will accept [link3] which has sink type [t2] *) (*Insert a [(t3, t2)] link*) let (Augmented_set {set =3D set3; accepts =3D a3; cc =3D cc3} : (t3, _) augmented_set)= =3D insert_link link3 set (cc2 a1) in (* - [a3] says that [set3] accepts links with sink type [t3] ([t3]is the source type of [link3]) - [cc3] says that [set3] accepts links with sink types that its parent does (that is, any links with sink types [t1], [t2] or [t3]) *) (*There is just no way we can get insert [link4] into [set3]. The is no evidence we can produce that will allow a link with sink type [t4]. Try the below with any of [a1], [a2], [a3])*) (* let (Augmented_set {set =3D set4; accepts =3D a4; cc =3D cc4} =3D insert_link link4 set (cc3 a3) : (t3, _) augmented_set) in *) () end let _ =3D let module T =3D Test (M) in T.test () --=20 Shayne Fletcher --001a11432e0ad476ac053e6187cb Content-Type: text/html; charset=UTF-8 Content-Transfer-Encoding: quoted-printable

= On Fri, Oct 7, 2016 at 1:02 PM, Shayne Fletcher <shayne.fletche= r.50@gmail.com> wrote:
On Wed, Se= p 21, 2016 at 6:22 PM, Jeremy Yallop <yallop@gmail.com> wrote= :
I'll describe an interface based on these ideas th= at maintains the
properties you stipulate.=C2=A0 I'll leave the problem of building an implementation that satisfies the interface to you.=C2=A0 (In fact, the
interface is the tricky part and the implementation is straightforward
if you can treat all the type parameters as phantom.)

=E2=80=8BHow's this?

<= font face=3D"tahoma, sans-serif">module M : S =3D struct
...
=E2=80=8B
I've hi= t a problem with my attempt at an implementation actually :(

The iss= ue is, the program below as written seems to work, but, if the type [_ set]= is made abstract in the signature [S], typing breaks. Can somebody explain= where I'm going wrong?


module type S =3D sig
<= /div>

=C2=A0 type _ sink
<= font face=3D"tahoma, sans-serif">=C2=A0 type _ source
=C2=A0 type _ set =3D= (string * string) list (*Why can't this be abstract?*)
=C2=A0 type (&#= 39;source, 'sink) link

=C2=A0 type ('sink, 'se= t) accepts=C2=A0

=C2=A0 val mk_sink : string -> 'sink sink
= =C2=A0 val mk_source : string -> 'source source
=C2=A0 val mk_link := 'source source * 'sink sink -> ('source, 'sink) link
=C2=A0 type 'sink fresh_set =3D=C2=A0
=C2=A0 | Fresh= _set : {
=C2=A0 =C2=A0 set : 'set set;
=C2=A0 =C2=A0 accepts : ('si= nk, 'set) accepts;
=C2=A0 } -> 'sink fresh_set

=C2=A0 val create_set : 'sink sink -> 'sink fresh_set

<= /font>
=C2=A0 type ('sink, 'parent) augmented_set =3D
=C2= =A0 | Augmented_set : {
=C2=A0 =C2=A0 set : 'set set;
=C2=A0 =C2=A0 acc= epts: ('sink, 'set) accepts;
=C2=A0 =C2=A0 cc : 's. ('s, &#= 39;parent) accepts -> ('s, 'set) accepts
=C2=A0 } -> ('s= ink, 'parent) augmented_set

=C2=A0 val insert_link := =C2=A0
=C2=A0 =C2=A0 ('source, 'sink) link ->
=C2=A0 =C2=A0 = 'parent set ->=C2=A0
=C2=A0 =C2=A0 ('sink, 'parent) accepts = ->
=C2=A0 =C2=A0 ('source, 'parent) augmented_set

end

<= /font>
= module M : S =3D struct

=C2=A0 type 'sink sink =3D { name : string= }
=C2=A0 type 'source source =3D { name : string }

=C2=A0 type &#= 39;set set =3D (string * string) list
=C2=A0 type ('source, 'sink) = link =3D ('source source * 'sink sink)

=C2=A0 let mk_sink (na= me : string) : 'sink sink =3D {name}
=C2=A0 let mk_source (name : strin= g) : 'source source =3D {name}
=C2=A0 let mk_link ((source, sink) : = 9;source source * 'sink sink)=C2=A0
=C2=A0 =C2=A0 =C2=A0 : ('source= , 'sink) link =3D (source, sink)

=C2=A0 type ('sink, 'set)= accepts =3D=C2=A0
=C2=A0 | Accepts : ('sink, 'set) accepts<= /div>

= =C2=A0 type 'sink fresh_set =3D=C2=A0
=C2=A0 | Fresh_set : {
=C2=A0 =C2= =A0 set : 'set set;
=C2=A0 =C2=A0 accepts : ('sink, 'set) accep= ts;=C2=A0
=C2=A0 =C2=A0 } =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0-> 'sink fresh_set

=C2=A0 let= create_set (s : 'sink sink) : 'sink fresh_set =3D
=C2=A0 =C2=A0 Fr= esh_set { set =3D ([] : 'set set);=C2=A0
=C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0 accepts =3D (Accepts : ('sink, 'set) ac= cepts) }
=C2=A0=C2=A0
=C2=A0 type ('sink, 'parent) augmented_set = =3D
=C2=A0 | Augmented_set : {
=C2=A0 =C2=A0 set : 't set;
=
=C2=A0 =C2= =A0 accepts: ('sink, 't) accepts;
=C2=A0 =C2=A0 cc : 's. ('= s, 'parent) accepts -> ('s, 't) accepts
=C2=A0 } -> ('= ;sink, 'parent) augmented_set
=
=C2=A0 let insert_link=C2=A0<= /div>
=C2=A0 = =C2=A0 =C2=A0 (l : ('source, 'sink) link)=C2=A0
=C2=A0 =C2=A0 =C2= =A0 (s : 'parent set)
=C2=A0 =C2=A0 =C2=A0 (a : ('sink, 'parent= ) accepts) =C2=A0: ('source, 'parent) augmented_set =3D
=C2=A0 =C2= =A0 let {name =3D src} : 'source source =3D fst l in
=C2=A0 =C2=A0 let = {name =3D dst} : 'sink sink =C2=A0=3D snd l in
=C2=A0 =C2=A0 Augmente= d_set {
=C2=A0 =C2=A0 =C2=A0 set : 't set =3D (src, dst) :: s;
=C2=A0 = =C2=A0 =C2=A0 accepts =3D (Accepts : ('source, 't) accepts);=
=C2=A0= =C2=A0 =C2=A0 cc =3D fun (_ : (_, 'parent) accepts) -> (Accepts : (= _, 'parent) accepts)
=C2=A0 =C2=A0 }

end

module Test (E : S) = =3D struct

=C2=A0 open E

=C2=A0 type t1 and t2 and t3 and t4

=
=C2=A0 let snk1 : t1 sink =3D mk_sink "sink1"
=C2=A0 let snk2 : = t2 sink =3D mk_sink "sink2"
=C2=A0 let snk3 : t4 sink =3D mk_sink= "sink3"

=C2=A0 let src1 : t2 source =3D mk_source "sou= rce1"
=C2=A0 let src2 : t3 source =3D mk_source "source2"
=C2=A0 let link1 : (t2, =C2=A0t1) link =3D mk_link (src1, snk1) (*t2 src= , t1 sink*)
=C2=A0 let link2 : (t3, =C2=A0t1) link =3D mk_link (src2, snk1)= (*t3 src, t1 sink*)
=C2=A0 let link3 : (t3, =C2=A0t2) link =3D mk_link (sr= c2, snk2) (*t3 src, t2 sink*)
=C2=A0 let link4 : (t3, =C2=A0t4) link =3D mk= _link (src2, snk3) (*t3 src, t4 sink*)

=C2=A0 let test () =3D=C2=A0
=C2=A0 =C2=A0 (*Create a fresh set from a sink of type [t1]*)
=C2=A0 =C2= =A0 let (Fresh_set {set; accepts =3D a} : t1 fresh_set) =3D=C2=A0
=C2=A0 = =C2=A0 =C2=A0 create_set snk1 in
<= font face=3D"tahoma, sans-serif">=C2=A0 =C2=A0 (*
=C2=A0 =C2=A0 =C2=A0 - [a= ] is evidence [set] accepts links with sink type [t1]
=C2=A0 =C2=A0 *)

=
=C2=A0 =C2=A0 (*Insert a [(t2, t1) link]*)
=C2=A0 =C2=A0 let Augmented_set= =C2=A0
=C2=A0 =C2=A0 =C2=A0 =C2=A0 {set =3D set1; accepts =3D a1; cc =3D cc= 1} =3D=C2=A0
=C2=A0 =C2=A0 =C2=A0 insert_link link1 set a in
=C2=A0 =C2=A0 = (*
=C2=A0 =C2=A0 =C2=A0 - [a1] is evidence [set1] accepts links with sink t= ype [t2] ([t2] is
=C2=A0 =C2=A0 =C2=A0 =C2=A0 the source type of [link1])
= =C2=A0 =C2=A0 =C2=A0 - [cc] says that [set1] accepts links with sink types = that its
=C2=A0 =C2=A0 =C2=A0 =C2=A0 parent [set] does:
=C2=A0 =C2=A0 =C2= =A0 =C2=A0 - [cc1 a] provides evidence that says that [set1] will accept
= =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 [link2] which has sink type [t1] *)

=
=C2=A0 =C2=A0 (*Insert a [(t3, t1)] link*)
=C2=A0 =C2=A0 let Augmented_set=
=C2=A0 =C2=A0 =C2=A0 =C2=A0 {set =3D set2; accepts =3D a2; cc =3D cc2} =3D=
=C2=A0 =C2=A0 =C2=A0 insert_link link2 set (cc1 a) in
=C2=A0 =C2=A0 (*
=C2= =A0 =C2=A0 =C2=A0 - [a2] says that [set2] accepts links with sink type [t3]= ([t3] is
=C2=A0 =C2=A0 =C2=A0 =C2=A0 the source type of [link2])
=C2=A0 = =C2=A0 =C2=A0 =C2=A0 - [cc2] says that [set2] accepts links with sink types= that its
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 parent does:
=C2=A0 =C2=A0 =C2= =A0 =C2=A0 - [cc2 a1] provides evidence that says that [set2] will accept
= =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 [link3] which has sink type [t2]<= /div>
=C2=A0 = =C2=A0 *)

=C2=A0 =C2=A0 (*Insert a [(t3, t2)] link*)
=C2=A0 =C2=A0 let= (Augmented_set
=C2=A0 =C2=A0 =C2=A0 =C2=A0 {set =3D set3; accepts =3D a3; = cc =3D cc3} : (t3, _) augmented_set) =3D
=C2=A0 =C2=A0 =C2=A0 insert_link l= ink3 set (cc2 a1) in
=C2=A0 =C2=A0 (*
=C2=A0 =C2=A0 =C2=A0 - [a3] says that= [set3] accepts links with sink type [t3] ([t3]is
=C2=A0 =C2=A0 =C2=A0 =C2= =A0 the source type of [link3])
=C2=A0 =C2=A0 =C2=A0 - [cc3] says that [set= 3] accepts links with sink types that its
=C2=A0 =C2=A0 =C2=A0 =C2=A0 paren= t does (that is, any links with sink types [t1], [t2] or [t3])
=
=C2=A0 =C2= =A0 *)

=C2=A0 =C2=A0 (*There is just no way we can get insert [link4] = into [set3]. The
=C2=A0 =C2=A0 =C2=A0 is no evidence we can produce that wi= ll allow a link with sink
=C2=A0 =C2=A0 =C2=A0 type [t4]. Try the below wit= h any of [a1], [a2], [a3])*)
=C2=A0 =C2=A0 (*
=C2=A0 =C2=A0 let (Augmented_= set
=C2=A0 =C2=A0 =C2=A0 =C2=A0{set =3D set4; accepts =3D a4; cc =3D cc4} = =3D
=C2=A0 =C2=A0 =C2=A0 =C2=A0insert_link link4 set (cc3 a3) : (t3, _) aug= mented_set) in
=C2=A0 =C2=A0 *)

=C2=A0 =C2=A0 ()
end

=
let _ =3D le= t module T =3D Test (M) in T.test ()
--
Shayne Fletcher
--001a11432e0ad476ac053e6187cb--