I am trying to generate in Alloy two sets of classes, for instance, classes before a refactoring
application and classes after a refactoring application.
Suppose in the first set we have the following classes:
ALeft -> BLeft -> CLeft
Class1
Class2 -> Class3
-> Class4
meaning that ALeft is the parent of BLeft which in turn is the parent of CLeft, Class1 and
Class2, which in turn is the parent of Class3 and Class4.
On the other hand, following the same reasoning, we have in the second set the
following group of classes:
ARight -> BRight -> CRight
Class1'
Class2' -> Class3'
-> Class4'
Since each set represent the
same classes but in different chronological order (different states), it is necessary to guarantee the corresponding
equivalences, such as Class1 and Class1' are equivalent meaning that they have the same fields, methods, and so on (consider that the refactoring occurs only
in B and C classes) . For the same reasoning, Class2 and Class2', Class3 and Class3', Class4 and Class4' are also equivalent. In addition, we should have an equivalence among the methods in Left and Right classes. For instance, if we have a Left class method like:
public int leftClassMethod(){
new ALeft().other();
}
Then, there must be a corresponding Right class method like:
public int rightClassMethod(){
new ARight().other();
}
As suggested by Loic (in this discussion list), the equivalence of these classes started to be guaranteed but we have to complement the predicate classesAreTheSame below, in order to also guarantee the equivalence of their methods. Consider the model below:
abstract sig Id {}
sig ClassId, MethodId,FieldId extends Id {}
one sig public, private_, protected extends Accessibility {}
abstract sig Type {}
abstract sig PrimitiveType extends Type {}
one sig Long_, Int_ extends PrimitiveType {}
sig Class extends Type {
id: one ClassId,
extend: lone Class,
methods: set Method,
fields: set Field,
}
sig Method {
id : one MethodId,
param: lone Type,
return: one Type,
acc: lone Accessibility,
b: one Block
}
sig Block {
statements: one SequentialComposition
}
sig SequentialComposition {
first: one StatementExpression,
rest: lone SequentialComposition
}
abstract sig Expression {}
abstract sig StatementExpression extends Expression {}
sig MethodInvocation extends StatementExpression{
pExp: lone PrimaryExpression,
id_methodInvoked: one Method
}
sig AssignmentExpression extends StatementExpression {
pExpressionLeft: one FieldAccess,
pExpressionRight: one {Expression - newCreator - VoidMethodInvocation - PrimaryExpression - AssignmentExpression }
}
abstract sig PrimaryExpression extends Expression {}
sig this_, super_ extends PrimaryExpression {}
sig newCreator extends PrimaryExpression {
id_cf : one Class
}
sig FieldAccess {
pExp: one PrimaryExpression,
id_fieldInvoked: one Field
}
sig Left,Right extends Class{}
one sig ARight, BRight, CRight extends Right{}
one sig ALeft, BLeft, CLeft extends Left{}
pred law6RightToLeft[] {
twoClassesDeclarationInHierarchy[]
}
pred twoClassesDeclarationInHierarchy[] {
no disj x,y:Right | x.id=y.id
Right.*extend & Left.*extend=none
one r: Right | r.extend= none
one l:Left| l.extend=none
ARight.extend=none
ALeft.extend=none
BRight in CRight.extend
BLeft in CLeft.extend
ARight in BRight.extend
ALeft in BLeft.extend
#(extend.BRight) > 2
#(extend.BLeft) > 2
#(extend.ARight) = 1
#(extend.ALeft) = 1
CLeft.id=CRight.id
all m:Method | m in ((*extend).ALeft).methods => m !in ((*extend).ARight).methods
all m:Method | m in ((*extend).ARight).methods => m !in ((*extend).ALeft).methods
some Method
all r:Right | all l:Left| (r.extend= none and l.extend=none) implies classesAreTheSameAndSoAreTheirCorrespondingSons[r,l]
}
pred classesAreTheSameAndSoAreTheirCorrespondingSons[right,left: Class]{
classesAreTheSame[right,left]
all r: right.^~extend | one l :left.^~extend | classesAreTheSame[r,l] and classesAreTheSame[r.extend ,l.extend]
all l:left.^~extend | one r :right.^~extend | classesAreTheSame[r,l] and classesAreTheSame[r.extend ,l.extend]
}
pred classesAreTheSame[r,l: Class]{
r.id=l.id
r.fields=l.fields
#r.methods = #l.methods
all mr: r.methods | one ml: l.methods | mr.id = ml.id && mr.b != ml.b
all mr: l.methods | one ml: r.methods | mr.id = ml.id && mr.b != ml.b
all r1: r.methods, r2: l.methods | r1.id = r2.id =>
equalsSeqComposition[r1.b.statements, r2.b.statements]
}
pred equalsSeqComposition[sc1, sc2: SequentialComposition]{
equalsStatementExpression[sc1.first, sc2.first]
//#sc1.(*rest) = #sc2.(*rest)
}
pred equalsStatementExpression [s1, s2: StatementExpression]{
s1 in AssignmentExpression => (s2 in AssignmentExpression && equalsAssignment[s1, s2])
s1 in MethodInvocation => (s2 in MethodInvocation && equalsMethodInvocation[s1, s2])
s1 in VoidMethodInvocation => (s2 in VoidMethodInvocation && equalsVoidMethodInvocation[s1, s2])
}
pred equalsAssignment [ae, ae2:AssignmentExpression]{
equalsPrimaryExpression[(ae.pExpressionLeft).pExp, (ae2.pExpressionLeft).pExp]
equalsPExpressionRight[ae.pExpressionRight, ae2.pExpressionRight]
}
pred equalsPrimaryExpression[p1, p2:PrimaryExpression]{
p1 in newCreator => p2 in newCreator && equalsClassesId [p1.id_cf, p2.id_cf]
p1 in this_ => p2 in this_
p1 in super_ => p2 in super_
}
pred equalsPExpressionRight[e1, e2:Expression]{
e1 in LiteralValue => e2 in LiteralValue
e1 in MethodInvocation => e2 in MethodInvocation && equalsMethodInvocation[e1, e2]
}
pred equalsMethodInvocation[m1, m2:MethodInvocation]{
equalsPrimaryExpression[m1.pExp, m2.pExp]
m1.id_methodInvoked.id = m2.id_methodInvoked.id
m1.param = m2.param
}
pred equalsVoidMethodInvocation[m1, m2:VoidMethodInvocation]{
equalsPrimaryExpression[m1.pExp, m2.pExp]
m1.id_voidMethodInvoked.id = m2.id_voidMethodInvoked.id
m1.param = m2.param
}
run law6RightToLeft for 10 but 17 Id, 17 Type, 17 Class
My idea was identifying the corresponding methods (leftClassMethod() and rightClassMethod()) through their ids (which is guaranteed to be the same, according to the model). However, the predicate equalsSeqComposition is not working and the situation gets worse when i try to include the rest relation of the signature SequentialComposition in comparison (commented above in the predicate equalsSeqComposition). This last comparison is even more difficult since Alloy do not allow recursion and the same levels of inheritence as ordering is lost when you use transitive closure. Any idea how can i represent this in Alloy?
It is possible to call functions and predicate recursively in Alloy only if the recursion depth does not exeed 3 see : Programming recursive functions in alloy
For your problem, You can emulate the recursion you are trying to specify using the transitive closure operator.
I would rewrite your predicate classesAreTheSameAndSoAreTheirCorrespondingSons as follows :
pred classesAreTheSameAndSoAreTheirCorrespondingSons[right,left: Class]{
classesAreTheSame[right,left]
all r: right.^~extend | one l :left.^~extend | classesAreTheSame[r,l] and classesAreTheSame[r.extend ,l.extend]
all l:left.^~extend | one r :right.^~extend | classesAreTheSame[r,l] and classesAreTheSame[r.extend ,l.extend]
}
This predicate enforces that the two classes right and left given are the same, and that any classes r/l inheriting (directly or indirectly) right/left has one counter part in the classes l/r inheriting (directly or indirectly) left/right , respectively.
The checkclassesAreTheSame[r.extend ,l.extend] is meant to check that r and l are in the same levels of inheritence as ordering is lost when you use transitive closure.
Here is the small model I designed to play with your problem :
abstract sig Class {
id: Int,
extend: lone Class
}{
this not in this.^#extend
}
sig Left,Right extends Class{}
fact{
no disj x,y:Right | x.id=y.id
Right.*extend & Left.*extend=none
one r: Right | r.extend= none
one l:Left| l.extend=none
all r:Right | all l:Left| (r.extend= none and l.extend=none) implies classesAreTheSameAndSoAreTheirCorrespondingSons[r,l]
}
pred classesAreTheSameAndSoAreTheirCorrespondingSons[right,left: Class]{
classesAreTheSame[right,left]
all r: right.^~extend | one l :left.^~extend | classesAreTheSame[r,l] and classesAreTheSame[r.extend ,l.extend]
all l:left.^~extend | one r :right.^~extend | classesAreTheSame[r,l] and classesAreTheSame[r.extend ,l.extend]
}
pred classesAreTheSame[r,l: Class]{
r.id=l.id
}
run {} for exactly 10 Class
Good luck for the rest ;)
Related
I know that I can run monadic instructions sequentially inside monads in Kind language, like this:
Test: _
IO {
IO.print(Nat.show(2))
IO.print(Nat.show(3))
IO.print(Nat.show(4))
}
output:
2
3
4
But is it possible to run monadic instructions repeatedly, like this below?
Test: _
a = [2,1,3,4,5]
IO {
for num in a:
IO.print(Nat.show(num))
}
If it is possible how can I do it correctly?
Monads are usually represented by only two operators :
return :: a -> m(a) // that encapulapse the value inside a effectful monad
>>= :: m a -> (a -> m b) -> m b
// the monadic laws are omitted
Notice, the bind operator is naturally recursive, once it can compose two monads or even discard the value of one and the return can be thought of as a "base case".
m >>= (\a -> ... >>= (\b -> ~ i have a and b, compose or discard? ~) >>= fixpoint)
You just have to produce that sequence, which is pretty straightforward. For example, in Kind we represent monads as a pair which takes a type-for-type value and encapluse a polymorphic type.
type Monad <M: Type -> Type> {
new(
bind: <A: Type, B: Type> M<A> -> (A -> M<B>) -> M<B>
pure: <A: Type> A -> M<A>
)
}
In your example, we just have to trigger the effect and discard the value, a recursive definition is enough :
action (x : List<String>): IO(Unit)
case x {
nil : IO.end!(Unit.new) // base case but we are not worried about values here, just the effects
cons : IO {
IO.print(x.head) // print and discard the value
action(x.tail) // fixpoint
}
}
test : IO(Unit)
IO {
let ls = ["2", "1", "3", "4", "5"]
action(ls)
}
The IO as you know it will be desugared by a sequence of binds!
Normally in case of list it can be generalized like the mapM function of haskell library :
Monadic.forM(A : Type -> Type, B : Type,
C : Type, m : Monad<A>, b : A(C), f : B -> A(C), x : List<A(B)>): A(C)
case x {
nil : b
cons :
open m
let k = App.Kaelin.App.mapM!!!(m, b, f, x.tail)
let ac = m.bind!!(x.head, f)
m.bind!!(ac, (c) k) // the >> operator
}
It naturally discard the value and finally we can do it :
action2 (ls : List<String>): IO(Unit)
let ls = [IO.end!(2), IO.end!(1), IO.end!(3), IO.end!(4), IO.end!(5)]
Monadic.forM!!!(IO.monad, IO.end!(Unit.new), (b) IO.print(Nat.show(b)), ls)
So, action2 do the same thing of action, but in one line!.
When you need compose the values you can represent as monadic fold :
Monadic.foldM(A : Type -> Type, B : Type,
C : Type, m : Monad<A>, b : A(C), f : B -> C -> A(C), x : List<A(B)>): A(C)
case x {
nil : b
cons :
open m
let k = Monadic.foldM!!!(m, b, f, x.tail)
m.bind!!(x.head, (b) m.bind!!(k, (c) f(b, c)))
}
For example, suppose that you want to sum a sequence of numbers that you ask for the user in a loop, you just have to call foldM and compose with a simple function :
Monad.action3 : IO(Nat)
let ls = [IO.get_line, IO.get_line, IO.get_line]
Monadic.foldM!!!(IO.monad, IO.end!(0),
(b, c) IO {
IO.end!(Nat.add(Nat.read(b), c))
},
ls)
test : IO(Unit)
IO {
get total = action3
IO.print(Nat.show(total))
}
For now, Kind do not support typeclass so it make the things a little more verbose, but i think a new support to forM loops syntax can be thought in the future. We hope so :)
Can someone please explain the: "description of g"? How can f1 takes unit and returns an int & the rest i'm confused about too!!
(* Description of g:
* g takes f1: unit -> int, f2: string -> int and p: pattern, and returns
* an int. f1 and f2 are used to specify what number to be returned for
* each Wildcard and Variable in p respectively. The return value is the
* sum of all those numbers for all the patterns wrapped in p.
*)
datatype pattern = Wildcard
| Variable of string
| UnitP
| ConstP of int
| TupleP of pattern list
| ConstructorP of string * pattern
datatype valu = Const of int
| Unit
| Tuple of valu list
| Constructor of string * valu
fun g f1 f2 p =
let
val r = g f1 f2
in
case p of
Wildcard => f1 ()
| Variable x => f2 x
| TupleP ps => List.foldl (fn (p,i) => (r p) + i) 0 ps
| ConstructorP (_,p) => r p
| _ => 0
end
Wildcard matches everything and produces the empty list of bindings.
Variable s matches any value v and produces the one-element list holding (s,v).
UnitP matches only Unit and produces the empty list of bindings.
ConstP 17 matches only Const 17 and produces the empty list of bindings (and similarly for other integers).
TupleP ps matches a value of the form Tuple vs if ps and vs have the same length and for all i, the i-th element of ps matches the i-th element of vs. The list of bindings produced is all the lists from the nested pattern matches appended together.
ConstructorP(s1,p) matches Constructor(s2,v) if s1 and s2 are the same string (you can compare them with =) and p matches v. The list of bindings produced is the list from the nested pattern match. We call the strings s1 and s2 the constructor name.
Nothing else matches.
Can someone please explain the: "description of g"? How can f1 takes unit and returns an int & the rest i'm confused about too!!
The function g has type (unit → int) → (string → int) → pattern → int, so it takes three (curried) parameters of which two are functions and one is a pattern.
The parameters f1 and f2 must either be deterministic functions that always return the same constant, or functions with side-effects that can return an arbitrary integer / string, respectively, determined by external sources.
Since the comment speaks of "what number to be returned for each Wildcard and Variable", it sounds more likely that the f1 should return different numbers at different times (and I'm not sure what number refers to in the case of f2!). One definition might be this:
local
val counter = ref 0
in
fun uniqueInt () = !counter before counter := !counter + 1
fun uniqueString () = "s" ^ Int.toString (uniqueInt ())
end
Although this is just a guess. This definition only works up to Int.maxInt.
The comment describes g's return value as
[...] the sum of all those numbers for all the patterns wrapped in p.
Since the numbers are not ascribed any meaning, it doesn't seem like g serves any practical purpose but to compare the output of an arbitrarily given set of f1 and f2 against an arbitrary test that isn't given.
Catch-all patterns are often bad:
...
| _ => 0
Nothing else matches.
The reason is that if you extend pattern with additional types of patterns, the compiler will not notify you of a missing pattern in the function g; the catch-all will erroneously imply meaning for cases that are possibly yet undefined.
Try flow link.
Here's a simple bounded polymorphism example that doesn't work the way I'd expect it to:
// #flow
function thisBreaks<T: 'a' | 'b'>(x: T): T {
if (x === 'a') {
return 'a'
} else {
return 'b'
}
}
function thisWorks<T: 'a' | 'b'>(x: T): T {
return x
}
const a = 'a'
const aPrime: 'a' = thisWorks(a)
const b = 'b'
const bPrime: 'b' = thisWorks(b)
5: return 'a'
^ string. This type is incompatible with the expected return type of
3: function thisBreaks<T: 'a' | 'b'>(x: T): T {
^ some incompatible instantiation of `T`
7: return 'b'
^ string. This type is incompatible with the expected return type of
3: function thisBreaks<T: 'a' | 'b'>(x: T): T {
^ some incompatible instantiation of `T`
I would have expected the first example to work, since e.g. the x === 'a' check could refine T to 'a', right?
This is not possible and shouldn't be possible. Here is an example that shows why:
function test<T: number | string>(x: T): T {
if (typeof x === 'number') {
return 1;
} else {
return 'b'
}
}
test((5: 5));
The function is supposed to return value of type 5, but returns 1 instead.
So, what happens? We have some unknown type T and we know that T <: string | number (T is subtype of string | number). After we refine x, we know that T is a subtype of number. It doesn't mean that T is number. It can be 5, like in the example, or 1 | 2 | 3. Knowing that T is subtype of number is not enough to create a value of T. To do that we need to know lower bound of T, but there is no way to know it.
The last question is: why is you example apparently safe then? It's simple: if T <: 'a', then it can only be 'a' (or empty, but it doesn't really matter). There are no other subtypes of 'a'. So, theoretically, Flow could support that, but its not very practical: if you know that x is 'a', than you can just return x
Say I have this record:
type alias Rec = { a : Int }
And, for example, a function that takes two of these and sums their integers.
f: Rec -> Rec -> Int
This can be implemented using record accessors (i.e. f x y = x.a + y.a), but is there a way to use pattern matching to extract both integers?
Obviously, these two do not work because they would be binding two different numbers to the same variable:
f {a} {a} = a + a
f x y = case (x, y) of ({a}, {a}) -> a + a
There seems to be no such way in the current Elm language. In other functional languages such as ML and Haskell, you could write patterns inside records like:
$ sml
Standard ML of New Jersey v110.74 [built: Sat Oct 6 00:59:36 2012]
- fun func {field=x} {field=y} = x+y ;
val func = fn : {field:int} -> {field:int} -> int
- func {field=123} {field=45} ;
val it = 168 : int
You might as well make a feature request to the developer(s) of Elm - or ask a question in the community mailing list at least.
P.S. After a quick search, I found such a proposal to add ML-like pattern matching on record fields in Elm, but it seems to have been turned down.:-(
There's no way to do this currently. There is pattern aliasing (as) but it only works for a whole pattern, so this is invalid:
type alias Rec = { a : Int }
f: Rec -> Rec -> Int
f { a as xa } { a as ya } = xa + ya
main = f { a = 1 } { a = 2 }
results in:
Detected errors in 1 module.
-- SYNTAX PROBLEM --------------------------------------------------------------
I ran into something unexpected when parsing your code!
4| f { a as xa } { a as ya } = xa + ya
^
I am looking for one of the following things:
a closing bracket '}'
whitespace
I Know F# have the MAP, but I wanna use the .NET Dictionary. This dict have key as string and values as F# values + the dict, ie:
type ExprC =
| StrC of string
| BoolC of bool
| IntC of int32
| DecC of decimal
| ArrayC of int * array<ExprC>
| RelC of RelationC
and RelationC = Dictionary<string, ExprC>
Now, the problem I wanna solve is how provide the RelationC type with structural equality. If is required to encapsulate the actual storage, how create a container that is a replacement for Dictionary, use it for mutable operations and have structural equality?
With the current answer, this code not work (of curse the implementation is not complete, however, this not even compile):
[<CustomEquality; CustomComparison>]
type MyDict() =
inherit Dictionary<string, ExprC>()
override this.Equals x =
match x with
| :? MyDict as y -> (this = y)
| _ -> false
override this.GetHashCode () =
hash this
interface System.IComparable with
member x.CompareTo yobj =
match yobj with
| :? MyDict as y -> compare x y
| _ -> invalidArg "MyDict" "cannot compare values of different types"
and [<StructuralEquality;StructuralComparison>] ExprC =
| IntC of int
| StrC of string
| MapC of MyDict
This is the error:
Error FS0377: This type uses an invalid mix of the attributes
'NoEquality', 'ReferenceEquality', 'StructuralEquality',
'NoComparison' and 'StructuralComparison' (FS0377)
If you absolutely must use Dictionary<string, ExprC>, you could derive from Dictionary<'k, 'v> and override Equals:
type MyDict() =
inherit Dictionary<string, ExprC>()
override this.Equals x =
true // real implementation goes here
override this.GetHashCode () =
0 // real implementation goes here
Here, you'd need to implement Equals to have structural equality, and you'll need to implement GetHashCode to match you Equals implementation.
Another alternative, if you don't need the concrete class Dictionary<'k, 'v>, is to define your own class that implements IDictionary<TKey, TValue>.
While possible, this sounds like a lot of work. It'd be much easier to use a Map, which has structural equality by default:
let m1 = Map.ofList [("foo", 1); ("bar", 2); ("baz", 3)]
let m2 = Map.ofList [("bar", 2); ("foo", 1); ("baz", 3)]
let m3 = Map.ofList [("bar", 2); ("foo", 1); ("baz", 4)]
> m1 = m2;;
val it : bool = true
> m1 = m3;;
val it : bool = false
Regarding the question at the end of the updated original post: What is the reason for "This type uses an invalid mix..."? This is a bug in the F# compiler, the error message is misleading, see Github. The solution is to simply remove all attributes from MyDict.