I had created a simple version of linked list using alloy . Now I want to create a linked list in which I could perform insertion and deletion. I have just begun coding in alloy. for now I am having trouble doing complex operations like using functions and utilities . If I could get some examples of how I could use utilities and functions as well as how I could actually perform insertion and deletion in alloy . I'd appreciate your help.
sig node{}
sig linked
{
ele:set node,
link:ele->lone ele,
head:lone ele
}{
node = ele
all x:ele | x in head.*link && head not in x.link && #x.link <=1
}
fact{
all l:linked| all e:l.ele| e->e not in l.link //no self loop
}
fact
{
all l:linked|no e : l.ele | (e in e.^(l.link )) //acyclic
}
pred a (l:linked,x:node)
{
x in l.ele
}
run a for 6 node,1 linked
Your approach is kind of confusing, it could be much simpler. I would do it like this
sig Node{
next : lone Node
}
one sig Head in Node {} -- head node is still a node
fact{
all n : Node | n not in n.^next -- no cycles
no next.Head -- no node points to Head
all n : Node - Head | some next.n -- for all other nodes, there has to be someone pointing to them
}
run {} for 10
This model is static, in order to make the model dynamic, you need to understand de concept of States. I recommend you'd read Software Abstractions, written by the author of Alloy. A dynamic approach for the linked list would be too complex for you to understand at this point, you should do some simpler exercise.
The basic idea of states is (exercise based on the address book example in the book):
static example:
sig State {}
abstract sig Target {}
sig Email extends Target {}
abstract sig Name extends Email {
name : set State,
addr : Target some -> State
}
sig Group, Alias extends Name {}
fact {
all a : Alias | lone a.addr
no n : Name | n in n.^addr
}
run {}
dynamic example, in the local state idiom (= a way to express the states, there is also a global state idiom and an event idiom). Take a look at the predicates
open util/ordering[State]
sig State {}
abstract sig Target {}
sig Email extends Target {}
abstract sig Name extends Email {
name : set State,
addr : Target -> State
}
sig Group, Alias extends Name {}
fact {
all s : State {
all a : Alias & name.s | lone a.addr.s
no n : name.s | n in n.^(addr.s)
addr.s in name.s -> Target
addr.s :> Name in Name -> name.s
}
}
run {} for 3 but exactly 1 State
-- adding a name n, for a given pre state s and post state s'
pred addName [n : Name, s,s' : State] {
-- the name must not exist in the pre state
n not in name.s
-- the relation names in the post state is what is was
-- in the pre state in addition to the new name
name.s' = name.s + n
-- the address relation stays the same
addr.s' = addr.s
}
run addName for 3 but 2 State
pred addTarget [n : Name, t : Target, s,s' : State] {
t not in n.addr.s
name.s' = name.s
addr.s' = addr.s + n->t
}
run addTarget for 3 but 2 State
You can also take a look at the following slides.
You don't need to make the model "dynamic" in order to model operations like insertion and deletion. Look at this topic (doubly-linked-list-in-alloy) where I gave an answer on how to model the reverse operation for a doubly-linked list, and then let us know if that wasn't helpful enough. The basic idea you'll see there is to create a predicate that takes arguments for both pre-state and post-state, and asserts how the two are related. For example, your insertion predicate could look like
// l - list in the pre-state
// x - node to be inserted
// l' - list in the post-state
pred insert (l: linked, x: node, l': linked) {
l'.ele = l.ele + x
...
}
Related
Through a parent contract, I want to be able to originate multiple child contracts. How can I do this in LIGO?
Check the contract factory example: https://ligolang.org/docs/tutorials/inter-contract-calls/inter-contract-calls/#contract-factories
The code they are using is available here: https://gitlab.com/ligolang/ligo/-/blob/dev/gitlab-pages/docs/tutorials/inter-contract-calls/examples/contracts/ligo/CreateAndCall.ligo
Unfortunately, Tezos.create_contract does not work well in practice. It only works if the child contract is extremely simple. The child code must either be written entirely inside the Tezos.create_contract call, or all of the definitions it uses must be [#inline]'d. If not all definitions are inlined, you will get the somewhat cryptic error "Not all free variables could be inlined in Tezos.create_contract usage."
A better alternative should be provided in some future Ligo version. Hopefully soon-ish.
In the meantime there is a workaround: compile your child contract separately, and use inline %Michelson with CREATE_CONTRACT, possibly using #include to include the compiled .tz file. Here is an example in Cameligo:
type child_storage = unit
type create_contract_args =
[#layout:comb]
(* order matters because we will cross the Michelson boundary *)
{ delegate : key_hash option;
balance : tez;
storage : child_storage }
type create_contract_result =
[#layout:comb]
{ operation : operation;
address : address }
[#inline] let create_contract =
[%Michelson ({|{ UNPAIR 3;
CREATE_CONTRACT
#include "./child.tz"
;
PAIR
}|} : create_contract_args -> create_contract_result)]
let main (_ : unit * unit) : operation list * unit =
let {operation; address = _} =
create_contract { delegate = (None : key_hash option);
balance = Tezos.get_amount ();
storage = () } in
([operation], ())
I'm trying to use the module type Partial_information which is constructed via the functor Make_partial_information as the type of the field contents in the type Cell.t. However, I'm getting the error Unbound module Partial_information.
open Core
(* module which is used as argument to functor *)
module type Partial_type = sig
type t
val merge : old:t -> new_:t -> t
end
(* type of result from functor *)
module type Partial_information = sig
type a
type t = a option
val merge : old:t -> new_:t -> t
val is_nothing : t -> bool
end
(* The functor *)
module Make_partial_information(Wrapping : Partial_type):
(Partial_information with type a = Wrapping.t)
= struct
type a = Wrapping.t
type t = a option
let merge ~(old : t) ~(new_ : t) =
match (old, new_) with
| (None, None) -> None
| (None, Some a) -> Some a
| (Some a, None) -> Some a
| (Some a, Some b) -> (Wrapping.merge ~old:a ~new_:b) |> Some
let is_nothing (it: t) : bool = (is_none it)
end
(* Checking to make sure understanding of functor is correct *)
module Int_partial_type = struct
type t = int
let merge ~old ~new_ = new_ [##warning "-27"]
end
module Int_partial_information = Make_partial_information(Int_partial_type)
(* Trying to use _any_ type which might have been created by the functor as a field in the record *)
module Cell = struct
type id = { name : string ; modifier : int }
type t = {
(* Error is here stating `Unbound module Partial_information` *)
contents : Partial_information.t ;
id : id
}
end
Module types are specifications for modules. They do not define types by themselves. They are also not constructed by functors in any way.
Consequently, it is hard to tell what you are trying to do.
As far I can see, you can simply define your cell type with a functor:
module Cell(P : Partial_information) = struct
type id = { name : string ; modifier : int }
type partial
type t = {
contents : P.t;
id : id
}
end
Or it might be even simpler to make the cell type polymorphic:
type 'a cell = {
contents : 'a;
id : id
}
since the type in itself is not particularly interesting nor really dependent upon
the type of contents.
P.S:
It is possible to use first class modules and GADTs to existentially quantify over a specific implementation of a module type. But it is unclear if it is worthwhile to explode your complexity budget here:
type 'a partial_information = (module Partial_information with type a = 'a)
module Cell = struct
type id = { name : string ; modifier : int }
type t = E: {
contents : 'a ;
partial_information_implementation: 'a partial_information;
id : id
} -> t
end
I'm writing a tool that generates ml stubs from mli files. I have the meaningful mappings complete (var f : int -> float to let f _ = 0.), but I'm having a little trouble reasoning about the AST nodes for classes and modules, specifically the Pmty_* and Pcty_* nodes. These two types of nodes (given the type hierarchy) seem to most most associated with mli files. Some of the trivial members--which appear in -dparsetrees of mli files (like Pmty_ident and Pcty_constr) have obvious mappings to nodes most associated with ml files (again by the hierarchy of the signature and structure types, in the aforementioned example to Pmod_ident and Pcl_constr). However, some of the nodes don't have an obvious parallel. Specifically, I'm having trouble reasoning about:
Pmty_with and Pmty_typeof - it seems like these two can never be parsed from a valid mli file; they only occur in a structure context that has a module_type as one of its members (I've checked my suspicions against all of OCaml's parser test files)
Pcty_signature - it seems like the only case this can occur is within a Psig_class_type (which I already directly map to Pstr_class_type); I against the OCaml test files and found a Pcty_signature only in this location, but are there other valid locations for it in an mli that I am missing?
Pcty_arrow - there are no test files containing this, so I can't be sure where it is valid, but my intuition says this also goes in a class_type context within a structure only (or within one of the other Pcty_*, in which case its conversion would be handled as a child by that node's mapping from Pcty_* to Pcl_*); is this incorrect?
I'm fairly deep into this and don't completely understand what's going on with all of these advanced language features and the AST nodes representing them, so here's an attempt at a simpler explanation of my questions:
Relevant types extracted from Parsetree:
type module_type_desc =
(* .. snip .. *)
| Pmty_with of module_type * with_constraint list
(* MT with ... *)
| Pmty_typeof of module_expr
(* module type of ME *)
type class_type_desc =
(* .. snip .. *)
| Pcty_signature of class_signature
(* object ... end *)
| Pcty_arrow of arg_label * core_type * class_type
(* T -> CT Simple
~l:T -> CT Labelled l
?l:T -> CT Optional l
*)
I believe that Pmty_with and Pmty_typeof can only occur in ml files (and not mli files). Is this assumption correct?
Can Pcty_signature occur as a node that isn't the child of a Psig_class_type?
Can a Pcty_arrow occur in a valid mli file? Where? As a child of what?
As I mentioned before, I'm fairly confident of my handling of every besides these two (modules and classes). In case the above isn't clear, here's an annotated snippet of the code that transforms Parsetree.signature -> Parsetree.structure with all of the non-module/class stuff removed for brevity:
(* Parsetree.signature -> Parsetree.structure *)
let rec stub signature_items =
(* Handles the module_type_desc *)
let rec stub_module_type module_type =
match module_type with
| { pmty_desc = type_; pmty_attributes = attrs; _ } ->
let expr =
match type_ with
| Pmty_ident ident -> Pmod_ident ident
| Pmty_signature signatures -> Pmod_structure (stub signatures)
| Pmty_functor (name, a, b) -> Pmod_functor (name, a, (stub_module_type b))
(* XXX: unclear if these two can occur in an mli *)
(* | Pmty_with (type_, constraints) -> _ TODO *)
(* | Pmty_typeof type_ -> _ TODO *)
| Pmty_extension ext -> Pmod_extension ext
| Pmty_alias name -> Pmod_ident name
in
make_module_expr expr attrs
in
(* The next three functions handles the module_type for single and multiple (rec) modules *)
let stub_module_decl module_decl =
match module_decl with
| { pmd_name = name; pmd_type = type_; pmd_attributes = attrs; _ } ->
make_module_binding name (stub_module_type type_) attrs
in
let stub_module module_ = Pstr_module (stub_module_decl module_)
and stub_modules modules = Pstr_recmodule (List.map stub_module_decl modules)
and stub_include include_ =
match include_ with
| { pincl_mod = module_type; pincl_attributes = attrs; _ } ->
Pstr_include (make_include_decl (stub_module_type module_type) attrs)
in
(* Handles classes (class_type) *)
let stub_classes classes =
(* Handles class_type_desc *)
let stub_class_descr descr =
let rec stub_class class_ =
let stub_class_type type_ =
match type_ with
| Pcty_constr (ident, types) -> Pcl_constr (ident, types)
| Pcty_signature class_ -> (* XXX: Is my below assumption true? *)
failwith "should be covered by Psig_class_type -> Pstr_class_type"
(* XXX: do we ever need to handle Pcty_arrow for mli files? *)
(* | Pcty_arrow (label, a, b) -> _ *)
| Pcty_extension ext -> Pcl_extension ext
| Pcty_open (override, ident, class_) ->
Pcl_open (override, ident, (stub_class class_))
in
match class_ with
| { pcty_desc = type_; pcty_attributes = attrs; _ } ->
make_class_expr (stub_class_type type_) attrs
in
match descr with
| { pci_virt = virt; pci_params = params; pci_name = name;
pci_expr = class_; pci_attributes = attrs } ->
make_class_decl virt params name (stub_class class_) attrs
in
Pstr_class (List.map stub_class_descr classes)
in
let transform_signature signature_item =
match signature_item with
| { psig_desc = signature; _ } ->
let desc =
match signature with
(* ... clip non-module/class stuff ... *)
| Psig_module module_ -> stub_module module_
| Psig_recmodule modules -> stub_modules modules
| Psig_include include_ -> stub_include include_
| Psig_class classes -> stub_classes classes
| Psig_class_type classes -> Pstr_class_type classes
in
make_str desc
in
List.map transform_signature signature_items
Unfortunately the module/class stuff is rather complex logic, so trimmed down there's still a lot. There are a ton of helps for creating the *_desc wrappers that encapsulate location in the file, attributes, etc., but those shouldn't be key to understanding how I'm handling modules and classes. But just for clarity, here are the types of all of the helpers:
val make_str : Parsetree.structure_item_desc -> Parsetree.structure_item
val make_module_expr :
Parsetree.module_expr_desc -> Parsetree.attributes -> Parsetree.module_expr
val make_module_binding :
string Asttypes.loc ->
Parsetree.module_expr -> Parsetree.attributes -> Parsetree.module_binding
val make_include_decl :
'a -> Parsetree.attributes -> 'a Parsetree.include_infos
val make_class_decl :
Asttypes.virtual_flag ->
(Parsetree.core_type * Asttypes.variance) list ->
string Asttypes.loc ->
'a -> Parsetree.attributes -> 'a Parsetree.class_infos
val make_class_expr :
Parsetree.class_expr_desc -> Parsetree.attributes -> Parsetree.class_expr
Relevant docs:
parsetree.ml (better than docs, because of some comments)
Edit: As an aside, besides reading documentation on these features (which didn't yield any AST patterns I didn't already know about), I recalled that the compiled can derive the interface from the implementation ocamlc -i. I traced down the variable in the compiler (it's called print_types) that's linked to this flag and found all of its uses, but it was not immediately apparent to me where at any of its uses code is called that derives the mli file (perhaps it is done progressively with the parse, since compiling produces a cmi?). If someone with more OCaml chops or more experience with the compiler could point me to where the mli file is derived, it may be easier to reverse engineer these module and class AST nodes.
Edit 2: I am also aware of How to auto-generate stubs from mli file?, however the answer there is "do it manually," which definitely conflicts with what I'm attempting! (The answerer also claims that such a tool would be trivial, but after pouring over these AST nodes for a while, I beg to differ!)
(I did not include the -dparsetree in my answer as it is heavy and not that interesting).
I believe that Pmty_with and Pmty_typeof can only occur in ml files (and not mli files). Is this assumption correct?
module M : module type of struct type t end with type t = int
As you can see from this valid mli file, this assumption isn't correct. .mli files require the same parser as .ml files do.
Can Pcty_signature occur as a node that isn't the child of a Psig_class_type?
class type c = object inherit object method x : int end end
Yes it can. Pcty_signature can occur anywhere a class type can occur. (note that there are two Pcty_signature here, one is the child of Pctf_inherit).
a Pcty_arrow occur in a valid mli file? Where? As a child of what?
class c' : int -> object method x : int end
Yes it can! And it can occur anywhere you'd indicate a class type.
Basically, you can consider that if a constructor can happen somewhere, then all the constructors of the same type can happen there too. Any type-related constructor can be in a .mli file (and non-type related constructors can happen too through the devious module type of).
If you have questions about where those are constructed, just take a look at parser.mly. Note that the same parser is used for the two file types.
This is a great game. Give me a list of AST Nodes, I'll write you a file that uses them all. :D
module K : module type of String
module M : Map.S with type key = K.t
class fakeref : K.t -> object
method get : K.t
method set : K.t -> unit
end
So, to summarize: Classes can take arguments, hence Pcty_arrow. Pcty_signature can also be the child of Psig_class, as shown above. The other two are standard module constructions that can absolutely appear in .mli files.
As for how ocamlc -i works ... well, it returns the signature inferred by the typechecker. There is no single point of access to this. You can read typing/HACKING.md if you want, but beware, the rabbit hole goes very deep. That being said, I do not think this will be all that helpful to achieve your goal.
My advice would be the following: all the nodes above are fairly easy to handle, except for with_type. This one is very hard, because it basically allows to compute in signatures. Just give up on that one for now.
Also, be aware that values, modules, module types, class and class types all have different namespaces. Pmty_ident x -> Pmod_ident x is not correct.
I'm trying to write an assert statement to the effect that once a mark is entered for
any student then the student always has a mark for that course (although it's possible the
mark may change). I already know how to check if the student has the mark or not, but i don't know how to do it in case the student doesn't have any mark to begin with. Also, how can i write a check statement for this assert statement?
sig Student, Tutor, Mark {}
sig Course {
reg : set Student,
alloc : Student -> Tutor,
result : Student -> Mark
}
This is what i tried
assert chekmark
{all c:Course | let c' = CO/next[c] |
some Student.(c.Result) => some Student.(c.Result)}
check checkmark for 3
But somehow it says: This expression failed to be typechecked.
Am i right or wrong,and how can i fix it if i'm right?
The problem is that the ordering on Courses is not going to be a solution for your problem. Using the ordering module simply places a total order on all courses (so CO/next[c] just returns the course immediately following c in that order), whereas you probably want to have a sequence of marks for each (Course, Student) pair.
Maybe something like this
sig Student, Tutor, Mark {}
sig Course {
reg : set Student,
alloc : Student -> Tutor,
result : set Grade
}
sig Grade {
student: one Student,
marks: seq Mark
}
Using Alloy sequences automatically gives you the property you want, that is, if the marks field is non-empty, then it is going to contain a sequence of Marks so no nulls in the middle are possible.
With this model, you might want to add a fact that enforces at most one grade per student per course.
fact oneGradePerStudentPerCourse {
all c: Course {
all s: c.reg |
lone {g: c.result | g.student = s}
}
}
What is difference between plus and plusElement (minus, minusElement) functions over the (immutable) List in practice?
operator fun <T> Collection<T>.plus(element: T): List<T>
fun <T> Collection<T>.plusElement(element: T): List<T>
Besides plus and minus being operators and therefore simplifiable to + and - respectively, I wanted to share an example, that may make it more clear, why plusElement or minusElement may also make sense to use. Basically that's the case when you do not want the overloaded operator methods to be called (e.g. plus(elements : Iterable<T>)), which may be the case when you are dealing with a list of lists.
Maybe the following samples make that clearer. In the samples all variable assignments show the type they got assigned when calling the respective function and contain the result in the comment at the end of the line. The variable ~ending naming convention is the following:
PlusT show calls to plus(element : T)
PlusIterable show calls to plus(elements : Iterable<T>)
PlusElementT show calls to plusElement(element : T)
Samples:
val someEntry = "some entry"
val listOfSomeEntry = listOf(someEntry)
val los : List<String> = listOf("listOfString")
val lsPlusT : List<String> = los.plus(someEntry) // [listOfString, some entry]
val lsPlusIterable1 : List<String> = los.plus(listOfSomeEntry) // [listOfString, some entry]
val lsPlusIterable2 : List<Any> = los.plus(listOf(listOfSomeEntry)) // [listOfString, [some entry]]
val lsPlusElementT1 : List<String> = los.plusElement(someEntry) // [listOfString, some entry]
val lsPlusElementT2 : List<Any> = los.plusElement(listOfSomeEntry) // [listOfString, [some entry]]
val lol : List<List<String>> = listOf(listOf("listOfList"))
// the following is basically not really correct as we are now dealing with a list of lists of strings, but it shows that llPlusT and llPlusIterable lead to the same (in this case probably wrong) result..
val llPlusT : List<Any> = lol.plus(someEntry) // [[listOfList], some entry]
val llPlusIterable : List<Any> = lol.plus(listOfSomeEntry) // [[listOfList], some entry]
val llPlusIterable2 : List<List<String>> = lol.plus(listOf(listOfSomeEntry)) // [[listOfList], [some entry]]
val llPlusElement1 : List<Any> = lol.plusElement(someEntry) // [[listOfList], some entry]
val llPlusElement2 : List<List<String>> = lol.plusElement(listOfSomeEntry) // [[listOfList], [some entry]]
As you can see when using + the overloaded variant plus(elements : Iterable<T>) might be used, which will probably make sense in most cases, but may not make sense in some others, e.g. (most of the times) when dealing with a list of lists. Instead of forcing the + to add a list of lists by using + listOf(anotherList), you may rather want to use plusElement (plusElement(anotherList)) or if you are sure you want to add only a single element, you may want to omit plus in favor of plusElement (probably a very rare and very special use case... that would be reflected with variant llPlusElement1).
Finally the plusElement or minusElement make it really clear from the naming that what you pass reflects 1 single item of the list, whereas + leaves that basically open... (you should see that however from the context, which with a list of list is probably not that clear anyways ;-)). And a disclaimer at the end: that should not mean that you should use a list of lists, but just in case you find something like that you have plus/minusElement at hand ;-)
The first one is an overloaded operator, as indicated by the operator keyword. It allows you to use the + operator with a List<T>.
The second one is a regular function, called in the normal function call style.
Both return a new List<T> with the element appended.
Transcript from the Kotlin REPL:
>>>val a = listOf(1, 2, 3)
>>>a + 4
[1, 2, 3, 4]
>>> a.plusElement(4)
[1, 2, 3, 4]
For more information about Kotlin operator overloading, see https://kotlinlang.org/docs/reference/operator-overloading.html.