私は楽しみのためにLINQtoZ3で遊んでいます(本番環境での使用ではありません)。
私はこの構文を最初に使用することになりました。
var i = 123;
var test2 = from t in TheormProver.NewTheorm()
let f = TheormProver.Func<int, bool>()
let a = TheormProver.Int
let g = TheormProver.Func<bool, int>()
where !f(a * 2) && g(f(g(f(4)))) == i * a && a < g(f(a))
select new { f = f.ToString(), g = g.ToString(), a, asd = "Test extra property" };
var solution = test2.Solve(); // Edited in for clarification
// note that test2 is a TheormProver<T> which has a "T Solve()" method defined.
staticTheromProver.Int
およびTheormProver.Func
methods/propertyは、現在、(名前に従って)基本型を返すだけです。
Variable<T>
今後は、値だけでなく、より多くの情報を含むタイプを作りたいと思います。
TL; DR:私が抱えている問題はf
、g
変数をフィールドとプロパティを追加できるカスタムタイプにしたいということですが、それでも、ここで得た構文でそれらを使用できるようにしたいです。句(つまり、メソッドとして/ Func
)。
では、独自のプロパティを追加/保持しながら、メソッド構文で使用できるカスタムタイプを作成するにはどうすればよいですか?
メソッドを呼び出しても何も起こらないか、where句を操作するので機能しないので、呼び出されたり実行されたりすることはありません。
例:
var test2 = from t in TheormProver.NewTheorm()
let f = TheormProver.Func<int, bool>()
let a = TheormProver.Int
where !f(a * 2) && a > 3 // f is used to create a method call expression
select new { f , a };
var testSolution = test2.Solve();
var fSolution = testSolution.f; // F is its own type with unique properties/fields.
var fConstraints = fSolution.Constraints;
var fSomeProperty = fSolution.SomeProperty;
foreach(var constraint in fConstraints)
{
//.....
}
これまでに作成した作業中の構文の簡単な例をモックアップしました。
http://liveworkspace.org/code/3Fm6JM$0
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Linq.Expressions;
namespace ConsoleApplication1
{
class TheormProver
{
public static int Int { get { return default(int); } } // Really this would return my Variable<int>
public static Func<T, TResult> Func<T, TResult>() { return default(Func<T, TResult>); } // Really this would return my Variable<Func<T, TResult>>
protected List<Expression> Constraints; // Holds constraints / where clauses that get translated into the Z3 language
//This gets called when we do the first "let" and gets us into the correctly typed world with a generic parameter
public virtual TheormProver<T> Select<T>(Func<TheormProver, T> sel)
{
return new TheormProver<T>(Constraints);
}
}
// This is what the user of the library sees and is returned by a from t in new TheormProver(). T will be the anonymous type from the last let
class TheormProver<T> : TheormProver
{
public TheormProver(List<Expression> Constraints)
{
}
// This gets called on subsequent "let"s, going from the anonymous type with one property "f" to one with 2, "f, g". Chaining this way allows as many lets as we want
public virtual TheormProver<U> Select<U>(Expression<Func<T, U>> sel)
{
return new TheormProver<T, U>(sel, Constraints.ToList());
}
public virtual TheormProver<T> Where(Expression<Func<T, bool>> constraint)
{
var result = (TheormProver<T>)this; // This should be a clone to allow composable queries
result.Constraints.Add(constraint);
return result;
}
public virtual T Solve(out bool foundSolution)
{
// TODO: Call Z3 and get a solution
foundSolution = false;
return default(T);
}
}
internal class TheormProver<T, U> : TheormProver<U>
{
private LambdaExpression Selector;
private TheormProver<T> InternalTheorumProver;
public TheormProver(Expression<Func<T, U>> selector, List<Expression> constraints)
: base(constraints)
{
Selector = selector;
InternalTheorumProver = new TheormProver<T>(constraints);
}
}
class Program
{
static void Main(string[] args)
{
var test = from t in new TheormProver()
let f = TheormProver.Func<int, bool>()
let g = TheormProver.Func<bool, int>()
let a = TheormProver.Int
where g(f(a)) == 0
select new { f, g, a };
bool foundSolution;
var testSolution = test.Solve(out foundSolution);
}
}
}