Я реализовал государственную монаду, и я работаю над включением LINQ «Синтаксис понимания» с помощью методов расширения.Что вызывает ошибку «Тип выражения в предложении let неверен».
Может ли кто-нибудь объяснить причину ошибки в названии? Возможно, метод расширения отсутствует или у него неправильная подпись. Непонятно, что более подробные аспекты работы LINQ и что-то вроде тривиального, как предложение let
.
Обращаем внимание: в других случаях подобные сообщения звучат в связи с предложением «выбрать» или «присоединиться»; Я не смог различить какое-либо сходство с моим примером ниже.
Этот пример компилируется и работает правильно:
namespace StateMonad {
using StateUnit = State<Unit,GCDState>;
using TupleUnit = State<Unit,GCDState>.StateTuple;
private static class TestClass {
// This usage compiles and runs fine.
private static readonly StateUnit GcdInner_Good =
(from s in State<Unit,GCDState>.Get
select new TupleUnit(Unit.unit,
s.A > s.B ? new GCDState(s.B, s.A-s.B)
: s.A < s.B ? new GCDState(s.B, s.A )
: s)
);
// continued below
Но это один не делает, генерируя ошибку интереса на первом let
:
// continued from above
// This usage fails to compile, with error as shown
private static readonly StateUnit GcdInner_Bad =
(from s in State<Unit,GCDState>.Get
let A = s.A // Generates error on "let":
let B = s.B // "The type of the expression in the let clause is incorrect.
// Type inference failed in the call to 'Select'."
select new TupleUnit(Unit.unit,
A > B ? new GCDState(B, A - B)
: A < B ? new GCDState(B, A )
: s)
);
}
}
Вот методы расширения, объявленные до сих пор:
public static class StateExtensions {
[Pure]public static State<TResult,TState> Select<TValue,TState,TResult>(this
State<TValue,TState> @this,
Func<TValue,State<TResult,TState>.StateTuple> projector
) where TResult:struct where TState:struct where TValue:struct {
projector.ContractedNotNull("projector");
return new State<TResult,TState>(s => projector(@this.EvalState(s)));
}
[Pure]public static State<TResult,TState> SelectMany<TValue,TState,TResult>(this
State<TValue,TState> @this,
Func<TValue,State<TResult,TState>> selector
) where TResult:struct where TState:struct where TValue:struct {
selector.ContractedNotNull("selector");
return @this.Bind(selector);
}
[Pure]public static State<TResult,TState> SelectMany<TValue,TState,T,TResult>(this
State<TValue,TState> @this,
Func<TValue, State<T,TState>> selector,
Func<TValue, T, TResult> projector
) where TResult:struct where TState:struct where TValue:struct where T:struct {
selector.ContractedNotNull("selector");
projector.ContractedNotNull("projector");
return new State<TResult, TState>(s => {
var value = @this.RunState(s).Value;
return new State<TResult, TState>.StateTuple(
projector(value, selector(value).RunState(s).Value) ,s);
});
}
}
И вот основные положения Государственная монада класс:
public struct State<TValue,TState> : IEquatable<State<TValue,TState>>
where TValue:struct where TState:struct {
public delegate StateTuple Transformer(TState state);
public State(Transformer transformer) : this() {
Contract.Requires(transformer != null);
_transformer = transformer;
}
[Pure]public State<TResult,TState> Bind<TResult> (
Func<TValue, State<TResult,TState>> selector
) where TResult:struct {
selector.ContractedNotNull("selector");
var @this = this;
return new State<TResult,TState>(state => {
var tuple = @this.RunState(state);
return selector(tuple.Value).RunState(tuple.State);
});
}
[Pure]public StateTuple RunState(TState state) { return _transformer(state); }
[Pure]public TValue EvalState(TState state) { return RunState(state).Value; }
[Pure]public TState ExecState(TState state) { return RunState(state).State; }
private readonly Transformer _transformer;
}
public struct StateTuple {
public StateTuple(Tuple<TValue, TState> content) : this(content.Item1,content.Item2) {
content.ContractedNotNull("content");
}
public StateTuple(TValue value, TState state) : this() {
_value = value; _state = state;
}
public TValue Value { get {return _value;} } readonly TValue _value;
public TState State { get {return _state;} } readonly TState _state;
#region Value Equality with IEquatable<T>.
/// <inheritdoc/>
[Pure]public override bool Equals(object obj) {
var other = obj as StateTuple?;
return other != null && other.Equals(obj);
}
/// <summary>Tests value-equality, returning <b>false</b> if either value doesn't exist.</summary>
[Pure]public bool Equals(StateTuple other) {
return this.Value.Equals(other.Value) && this.State.Equals(other.State);
}
/// <inheritdoc/>
[Pure]public override int GetHashCode() { unchecked { return Value.GetHashCode()^State.GetHashCode(); } }
/// <inheritdoc/>
[Pure]public override string ToString() {
Contract.Ensures(Contract.Result<string>() != null);
return String.Format("({0},{1})",Value,State);
}
/// <summary>Tests value-equality, returning <b>false</b> if either value doesn't exist.</summary>
[Pure]public static bool operator == (StateTuple lhs, StateTuple rhs) { return lhs.Equals(rhs); }
/// <summary>Tests value-inequality, returning <b>false</b> if either value doesn't exist..</summary>
[Pure]public static bool operator != (StateTuple lhs, StateTuple rhs) { return ! lhs.Equals(rhs); }
#endregion
}
Вот еще несколько утилит, необходимых для компиляции:
/// <summary>TODO</summary>
public static class State {
public static State<bool,TState> DoWhile<TState>(this
State<bool,TState>.Transformer body
) where TState:struct {
return new State<bool,TState>(state => {
State<bool,TState>.StateTuple tuple;
do { tuple = body(state); state = tuple.State; } while (tuple.Value);
return tuple;
});
}
/// <summary>Implements the Haskell operator (liftM): liftM f m = m >>= (\x -> return (f x))</summary>
public static State<B,TState> LiftM<TState,A,B>(this
State<A,TState> @this,
Func<A,B> func
) where TState:struct where A:struct where B:struct {
return @this.Bind(t => new State<B,TState>(s => new State<B,TState>.StateTuple(func(t),s)));
}
}
/// <summary>TODO</summary>
public static class State<TState> where TState:struct {
public readonly static State<TState, TState> Get
= new State<TState, TState>(s => new State<TState,TState>.StateTuple(s, s));
public static State<Unit,TState> Put(TState state) {
return new State<Unit,TState>(s => new State<Unit,TState>.StateTuple(Unit.unit,state));
}
#region Convenience extensions to Get() for efficiency
/// <summary>TODO</summary>
/// <typeparam name="TValue"></typeparam>
/// <typeparam name="TState"></typeparam>
/// <param name="selector"></param>
[Pure]public static State<TValue,TState> GetBind<TValue>(
Func<TState, State<TValue,TState>> selector
) where TValue:struct {
selector.ContractedNotNull("selector");
return new State<TValue,TState>(s => selector(s).RunState(s));
}
/// <summary>TODO</summary>
/// <typeparam name="TValue"></typeparam>
/// <typeparam name="TState"></typeparam>
/// <param name="selector"></param>
[Pure]public static State<TValue,TState> GetCompose<TValue>(
Func<TState,State<TValue,TState>> selector
) where TValue:struct {
selector.ContractedNotNull("selector");
return new State<TValue,TState>(s => selector(s).RunState(s));
}
/// <summary>TODO</summary>
/// <typeparam name="TValue"></typeparam>
/// <typeparam name="TState"></typeparam>
/// <param name="selector"></param>
[Pure]public static State<Unit,TState> GetComposePut(
Func<TState,TState> transform
) {
transform.ContractedNotNull("transform");
return new State<Unit,TState>(s => new State<Unit,TState>.StateTuple(Unit.unit,transform(s)));
}
/// <summary>TODO</summary>
/// <typeparam name="TValue"></typeparam>
/// <typeparam name="TState"></typeparam>
/// <param name="selector"></param>
[Pure]public static State<TValue,TState> GetSelect<TValue>(
State<TValue,TState>.Transformer projector
) where TValue:struct {
projector.ContractedNotNull("projector");
return new State<TValue,TState>(projector);
}
#endregion
}
@Codexer Не думаю; У меня есть пример в моем коде, который все еще не компилируется, когда я заменяю лямбда статической функцией. Аналогично, когда я оставляю использование в лямбде как поле, ссылается на 's'. –
Это все очень ошеломляет, но я мог бы предложить некоторое представление, если бы смог его собрать. Я не могу найти объявление StateTuple где угодно. Можно ли продолжать добавлять объявления до сборки? – recursive
Где определение 'State .Get'? Недостаточно определённых определений для компиляции. –
Lee