Idea: ExpressionLens<A, B>

Author: WorldMakerCreated Apr 3, 2026Updated Apr 3, 2026

An idea that occurred to me in thinking about Lens<A, B> that could be useful in contexts that use EF or similar (maybe even a world where Eff supports Expression compilation) would be a relatively pure subclass ExpressionLens<A, B>. Roughly something like (untested):

cs
using System.Linq.Expression;

public readonly struct ExpressionLens<A, B>(
    public readonly Expression<Func<A, B>> GetExp,
    public readonly Expression<Func<B, Expression<Func<A, A>> SetExp)
    : Lens(GetExp.Compile(), b => SetExp.Compile().Invoke(b).Compile());

The benefit would be reuse of the same underlying Lens in Linq contexts such as in an EF query using a .Select(MyExpressionLens.GetExp) which EF can translate to a database projection in many cases. (Off the top of my head I can't think of a good Linq example for SetExp, but there presumably is one. It also might be too hard to write a nested Expression in that way that compiles reliably, so it may be YAGNI and the idea to only provide GetExp.)

It would probably remain a subclass of Lens rather than the default for the same reason that the C# compiler will only compile a subset of Func<A, B> to Expression<Func<A, B>>. There would remain plenty of uses of Lens where you may not need those restrictions.

Also presumably it would be more complicated work to support a specialization of Prelude.lens(ExpressionLens<A, B>, ExpressionLens<B, C>) that can also return ExpressionLens<A, C>, but especially if that specialization were to exist that would lend additional reason to support an ExpressionLens subclass. .Select(lens(MyExpressionLens, MySubPropertyExpressionLens).GetExp) could be quite useful in some query scenarios.

I don't have any applications I support that use both EF and LanguageExt today so this is mostly an academic exercise for now for me, but thought it an interesting idea to float in case it sparks other ideas.