This name is ambiguous due to multiple matches: - alloy

I have an Alloy model, that have 2 signatures which have a relation that have the same name.
sig Model {
components : set Component
}
sig Port extends Element {
belongsTo : Component
}
sig Component extends Element{
belongsTo : Model,
ports : set Port
}
When I try to access these relation threw join the solver throws me:
A type error has occured:
This name is ambiguous due to multiple matches:
field this/Port <: belongsTo
field this/Component <: belongsTo
Is there any way to specify explicitly that I want to access to the relation belongTo of component and not the port one, when I do:
all m : m.belongsTo |
and m are models?
Thanks.

You can say
all x: m.(Component <: belongsTo) | ...

Related

how to set constraints on a ternary relation

I have this model
sig Factor {}
sig Rule { rule : some Factor }
sig RuleSet { rules : some Rule }
sig EventRuleProperty {}
sig Event {
rulesets : some RuleSet,
rule_properties : rulesets -> Rule -> EventRuleProperty
}
How do I write a fact to restrict the rules in Event.rule_properties have to belong to Event.ruleset?
I declared as
rule_properties : rulesets -> rulesets.rules -> EventRuleProperty
but got a syntax error
Answered there. Please ask such questions in a single place for Alloy users (here on at the Alloy forum) unless you don't get any answer for several days.

How to implement intersection type with overrides

I am creating a control manager that will be an abstract base for other control managers: ButtonManager, InputManager, PopupManager, etc. The controls share some similarity but not all. For instance, size and intent. I want to define shared types in ControlManager as well as an interface in ControlManager that uses these types.
All controls will have an intent, but not all controls will have the same set of intents, as the base set can be added to. I want to be able to create a base ControlIntent type in the abstract ControlManager class and extend it in derived classes.
I should note that I have ControlManager as an abstract class because I would like to enforce classes that implement ControlManager to define certain functionality such as setIntentClass, setSizeClass, etc
The control manager defines a type ControlIntent as
export type ControlIntent = 'Default' | 'Disabled'
ButtonManager that extends ControlManager then defines its intent type as
export type ButtonIntent = ControlManager.ControlIntent & 'Secondary' | 'Success' | 'Warning' | 'Danger'
The interface in ControlManager defines some shared options. Using intent as an example:
export interface IOptions {
controlIntent: ControlIntent
}
Then in ButtonManager I want to extend the options interface and override the intent property:
export interface IOptions extends ControlManager.IOptions {
controlIntent: ButtonIntent
}
Potentially I am missing the big picture, but it seems to me that I should be able to enforce my implemented control managers to have a size and intent with at least the typed options defined in the base class. 'Default' and 'Disabled' for intent, but be able to add new intents in the extended interfaces without having to create a new property.
To summarize:
All controls have a size and intent with at least a minimal set of predefined options. I can then use intersection in the different control managers to add to the predefined options, but would like to be able to define said options in the base interface and then extend them in derived interfaces.
Is this a practical design decision, and if so, how do I accomplish it? Many thanks to all contributors.
By "adding options" what you're doing is widening the type, not extending it. Extending is always a narrowing operation (placing more restrictions). So you want a union, not an intersection... if you try to intersect two types with no overlap, you get an empty type equivalent to never (sometimes the compiler will actually collapse the type to never and other times it will keep the intersection around but you will find you can't assign any useful values to it):
type ControlIntent = 'Default' | 'Disabled'
// note the parentheses I added because the operators don't have the precedence you think
type ButtonIntent = ControlIntent & ('Secondary' | 'Success' | 'Warning' | 'Danger') // oops
// check with IntelliSense: type Button = never
So the type you presumably mean is this:
type ControlIntent = 'Default' | 'Disabled'
type ButtonIntent = ControlIntent | ('Secondary' | 'Success' | 'Warning' | 'Danger')
// type ButtonIntent = "Default" | "Disabled" | "Secondary" | "Success" | "Warning" | "Danger"
That's great but the confusion between narrowing/extends/intersection and widening/super/union persists into your interfaces. The following definition (I'm changing the name to IButtonOptions so it can sit in the same namespace as IOptions) now becomes an error:
export interface IOptions {
controlIntent: ControlIntent
}
export interface IButtonOptions extends IOptions { // error!
// ~~~~~~~~~~~~~~
// Interface 'IButtonOptions' incorrectly extends interface 'IOptions'.
controlIntent: ButtonIntent
}
That's because IButtonOptions violates an important substitution principle: if IButtonOptions extends IOptions, then an IButtonOptions object is an IOptions object. Meaning that if you ask for an IOptions object, I can give you an IButtonOptions object and you will be happy. But since you asked for an IOptions object, you expect its controlIntent property to be 'Default' or 'Disabled'. You would be rightfully unhappy with me if your supposed IOptions object turned out to have some other value for controlIntent. You'd look at it, and say, "wait, what's this "Secondary" string here?
So you need to redesign your interfaces for this to work. You'll have to give up on the idea of IButtonOptions being a subtype of IOptions. Instead, you might consider making IOptions a generic type where the type of the controlIntent property can be specified by the generic parameter. Perhaps like this:
export interface IOptions<I extends string = never> {
controlIntent: ControlIntent | I;
}
export interface IButtonOptions extends IOptions<ButtonIntent> {
// don't even need to specify controlIntent here
}
const bo: IButtonOptions = {
controlIntent: "Success";
} // okay
So the I parameter must be assignable to string and it defaults to never, so that the type IOptions without a parameter specified is the same type as your original IOptions.
But now, IButtonOptions does not extend IOptions, but instead it extends IOptions<ButtonIntent>. Then everything works.
Keep in mind that if you do this, functions that used to expect an IOptions object parameter will now also have to be made generic:
function acceptOptionsBroken(options: IOptions) {}
acceptOptionsBroken(bo); // oops, error
// ~~
// Argument of type 'IButtonOptions' is not assignable to parameter of type 'IOptions<never>'.
Okay, hope that helps you proceed. Good luck!
function acceptOptions<I extends string>(options: IOptions<I>) {}
acceptOptions(bo); // okay, I is inferred as "Secondary" | "Success" | "Warning" | "Danger"

How to add restrictions to fields of a signature when there are two instances in the model

I have the following Alloy model which describes a group of people. to simplify the problem. Here is a sample code snip.
sig groupofpeople {
member: set person,
country: Country
}{
#person=2
}
sig people {
teamleader: Bool,
position: String
}
So now we have two peoples in a group. Next I want to add some restrictions to the people in the group. For example, I want the two people in a group to always have one team leader and one team member. I use the following fact to do this:
fact {
all n: people , m: people - n {
n.teamleader not in m.teamleader
}
}
Now I encounter a problem which keep me from moving forward. The desired model I'm looking for is that if a group's country is "US", then the position of the teamleader is "US_TL" and position of the team member is "US_TM". If the country is "UK" then the position of teamleader is "UK_TL" and position of the team member is "UK_TM", and so on.
I tried to add something like:
all n: groupofpeople {
(n.country in US => (
n.member.position="US_TL" or
n.member.position= "US_TM")) or
(n.country in UK => (
n.member.position ="UK_TL" or
n.member.position = "UK_TM"))
}
But there are obviously something wrong with the prediction and the model can't generate correct solutions for me. Could you help me to identify the problem in my model?
The model you posted here doesn't compile, so I can't really pinpoint the problem (since there are many, so of which might be just typos). What seems to be incorrect for sure is the or between the two implications in the last all quantifiers: based on your description of the task, it should be and instead.
If I understood the desired properties of your model, here's how I would rewrite it (and if that's not what you intended to achieve, please clarify your question and post a model that is syntactically correct):
open util/boolean
abstract sig Country {}
one sig US extends Country {}
one sig UK extends Country {}
sig GroupOfPeople {
member: set Person,
country: one Country
}{
#member=2
}
sig Person {
teamleader: Bool,
position: String
}
fact {
all g: GroupOfPeople {
all n: g.member, m: g.member - n {
n.teamleader not in m.teamleader
}
}
}
run {
all n: GroupOfPeople {
(n.country in US => (
n.member.position="US_TL" or
n.member.position= "US_TM"))
(n.country in UK => (
n.member.position ="UK_TL" or
n.member.position = "UK_TM"))
}
} for 5
Would it not be nicer to replace the defn of sig Person above by
abstract sig Person{position : String}
sig Leader, Follower extends Person
fact one_leader {
all g : GroupOfPeople | one (g.member & Leader)
}
and even better to put this fact in the invariant of GroupOfPeople:
one (member & Leader)

class properties are not available in generic method c#

I am calling a generic method with two different classes as below:
FillDataPointsInOrder<Metrics>(dataPoints.Where(O => O.SortOrder != null).OrderBy(O => O.SortOrder));
FillDataPointsInOrder<Metric>(angieStatsCmp.GetDataColumns());
private void FillDataPointsInOrder<T>(IEnumerable<T> dataPoints)
{
foreach (T dpoint in dataPoints)
{
if (!dpoint.IsPhone)
FillDrp(this.EmailDrp, dpoint.Name, dpoint.MetricId.ToString(), dpoint.VName);
if (dpoint.IsPhone && this.IsPhoneShop)
FillDrp(this.PhoneDrp, dpoint.Name, dpoint.MetricId.ToString(), dpoint.VName);
}
}
in "FillDataPointsInOrder" method I am getting compile errors :
'T' does not contain a definition for 'IsPhone' and no extension method 'IsPhone' accepting a first argument of type 'T' could be found (are you missing a using directive or an assembly reference?)
Same errors for Name , MetricId and VName properties.
Not sure why T is not able to access properties of Metrics and Metric.
If I remove the code from generic method and write it directly in foreach over dataPoints it is working fine.
Can somebody advise what is wrong here?
FillDataPointsInOrder only knows it will be called with a T. T could actually be string, int or anything.
If you want to call properties on T, you will have to use a where constraint.
But in this case it looks like your method does not even need to be generic.
If both Metric and Metrics share a base class or an interface that has the properties you need:
interface IMetric {
bool IsPhone {get; }
}
you could just have:
private void FillDataPointsInOrder(IEnumerable<IMetric> dataPoints)
Note that IEnumerable is covariant, so if Metric is a IMetric, IENumerable<Metric> is a IEnumerable<IMetric>
You need to at least tell the compiler something about T if you want to do that. Do you have an interface that has members like IsPhone, Name, MetricId, etc. that your classes implement?
If so you can add a 'where' constraint to your class definition:
public class Something<T> where T : ISomethingElse
...where ISomethingElse is the interface that implements IsPhone.

Ninject: Binding an interface with a generic that is also an interface

I have searched this issue but with no luck. Here we go.
Suppose I have an interface:
interface IQueryRepository<T> where T : class
and I want to bind any requests for:
IQueryRepository<IClient>
to:
ConcreteQueryRepository<Client>
I've tried the obvious:
Bind<IGenericQueryRepository<IClient>>().To<ConcreteQueryRepository<Client>>()
But I get an error:
ConcreteQueryRepository<Client> cannot be used as type parameter 'TImplementation' in
the generic type or method 'Ninject.Syntax.IBindingToSyntax<T>.To<TImplementation>()'
There is no implicit reference conversion from 'ConcreteQueryRepository<Client>'
to 'IGenericQueryRepository<IClient>'
But I don't understand why since GenericQueryRepository implements IGenericQueryRepository and Client implements IClient.
I would like Ninject to give me a concrete generic repository where T is Client. I want this to avoid using concrete types in the code.
Can it be done?
This has to do with Covariance and Contravariance.
In your question you mentioned the following:
... GenericQueryRepository implements IGenericQueryRepository and Client implements IClient.
Let's make it simpler by using fruits: Fruit implements IFruit. We'll also create a Tree class.
public interface IFruit { }
public class Fruit : IFruit { }
public class Tree<T> where T : IFruit { }
Tree<IFruit> tree = new Tree<Fruit>() // error
This will reproduce the same kind of error you're experiencing. Why? Simple.
Though Fruit implements IFruit, an Fruit Tree doesn't implement a IFruit Tree. There is no cast possible between the Fruit Tree and the IFruit Tree, although you would expect it. They are both Trees, but with a different type parameter. The fact that their type parameters are related to each other, doesn't matter.
In other words: there is no cast possible between the Fruit Tree and the IFruit Tree, because their type parameters don't match.
In general, when casting with generics, make sure their type parameters match. However, there are a few exceptional cases. See Variance in Generic Interfaces.
In your case, you could fix it by using IClient as type parameter for the GenericQueryRepository class. Doing this will allow casting because the type parameters match. But I don't know your application architecture, so this fix might be inapplicable in your case.
EDIT: To make it easier to understand, copy paste the code below and see what the compiler says.
interface IFruit { }
class Fruit : IFruit { }
interface ITree<T> where T : IFruit { }
class Tree<T> : ITree<T> where T : IFruit { }
class Program
{
static void Main(string[] args)
{
ITree<Fruit> test1 = new Tree<Fruit>(); // compiles: type parameters match
ITree<IFruit> test2 = new Tree<Fruit>(); // fails: type parameters don't match
ITree<Fruit> test3 = new Tree<IFruit>(); // fails: type parameters don't match
ITree<IFruit> test4 = new Tree<IFruit>(); // compiles: type parameters match
IEnumerable<IFruit> test5 = new List<Fruit>(); // compiles: this is one of the exceptional cases
}
}
That should clear things up about what is and what is not possible.
I've had the same problem when trying to bind a Dapper query to an interface type, thinking about it, it seems to make sense that Dapper can't instantiate an Interface type.
The interface is only a contract and does not know about how to instantiate a concrete implementation of it.
Dapper needs a type that is concrete implementation of the interface type otherwise Dapper would also have to know which concrete implementation of the interface to instantiate, and in that case Dapper would behave like a DI container which, indeed, it isn't.

Resources