Lenses are working, implemented addition of an operator to the parser.
This commit is contained in:
parent
b517d4f032
commit
fce4e7f53c
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -1,4 +1,5 @@
|
|||
/tests_results
|
||||
/main.exe
|
||||
/main.exe.mdb
|
||||
/*Generated.cs
|
||||
/*Generator.exe
|
|
@ -18,10 +18,10 @@ public static class LexerGenerator {
|
|||
Case("StringOpen"),
|
||||
Case("StringClose")),
|
||||
Record("Rule",
|
||||
Field("S", "oldState"),
|
||||
Field("Lexer.S", "oldState"),
|
||||
Field("string", "description"),
|
||||
Field("Func<GraphemeCluster, bool>", "test"),
|
||||
Field("S", "throughState"),
|
||||
Field("S", "newState"))));
|
||||
Field("Lexer.S", "throughState"),
|
||||
Field("Lexer.S", "newState"))));
|
||||
}
|
||||
}
|
52
Parser.cs
52
Parser.cs
|
@ -8,32 +8,44 @@ using S = Lexer.S;
|
|||
using Lexeme = Lexer.Lexeme;
|
||||
using static Global;
|
||||
|
||||
using PrecedenceDAG = System.Collections.Immutable.ImmutableDictionary<string, Parser.DAGNode>;
|
||||
using PrecedenceDAG = ImmutableDefaultDictionary<string, Parser.DAGNode>;
|
||||
|
||||
public static partial class Parser {
|
||||
public static PrecedenceDAG DefaultPrecedenceDAG = new PrecedenceDAG();
|
||||
public static DAGNode EmptyDAGNode = new DAGNode(
|
||||
infixLeftAssociative: ImmutableList<Operator>.Empty,
|
||||
prefix: ImmutableList<Operator>.Empty,
|
||||
closed: ImmutableList<Operator>.Empty,
|
||||
terminal: ImmutableList<Operator>.Empty,
|
||||
infixRightAssociative: ImmutableList<Operator>.Empty,
|
||||
infixNonAssociative: ImmutableList<Operator>.Empty,
|
||||
postfix: ImmutableList<Operator>.Empty,
|
||||
successorNodes: ImmutableList<string>.Empty
|
||||
);
|
||||
|
||||
public static DAGNode With(DAGNode node, Operator @operator) {
|
||||
var newNode = @operator.fixity.Match(
|
||||
Closed: () => node.lens.closed.Cons(@operator),
|
||||
InfixLeftAssociative: () => node.lens.infixLeftAssociative.Cons(@operator),
|
||||
InfixRightAssociative: () => node.lens.infixRightAssociative.Cons(@operator),
|
||||
InfixNonAssociative: () => node.lens.infixNonAssociative.Cons(@operator),
|
||||
Prefix: () => node.lens.prefix.Cons(@operator),
|
||||
Postfix: () => node.lens.postfix.Cons(@operator),
|
||||
Terminal: () => node.lens.terminal.Cons(@operator)
|
||||
public static PrecedenceDAG DefaultPrecedenceDAG
|
||||
= new PrecedenceDAG(EmptyDAGNode);
|
||||
|
||||
public static Whole With<Whole>(this ILens<DAGNode, Whole> node, Operator @operator) {
|
||||
return @operator.fixity.Match(
|
||||
Closed:
|
||||
() => node.Closed().Cons(@operator),
|
||||
InfixLeftAssociative:
|
||||
() => node.InfixLeftAssociative().Cons(@operator),
|
||||
InfixRightAssociative:
|
||||
() => node.InfixRightAssociative().Cons(@operator),
|
||||
InfixNonAssociative:
|
||||
() => node.InfixNonAssociative().Cons(@operator),
|
||||
Prefix:
|
||||
() => node.Prefix().Cons(@operator),
|
||||
Postfix:
|
||||
() => node.Postfix().Cons(@operator),
|
||||
Terminal:
|
||||
() => node.Terminal().Cons(@operator)
|
||||
);
|
||||
// op.fixity, parts, holes
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public static PrecedenceDAG With(PrecedenceDAG precedenceDAG, Operator @operator) {
|
||||
precedenceDAG.lens(@operator.precedenceGroup);
|
||||
/*precedenceDAG.update(
|
||||
dagNode => dagNode.Add(@operator)
|
||||
);*/
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
public static PrecedenceDAG With(PrecedenceDAG precedenceDAG, Operator @operator)
|
||||
=> precedenceDAG.lens()[@operator.precedenceGroup].With(@operator);
|
||||
|
||||
public static void DagToGrammar(DAGNode precedenceDAG) {
|
||||
|
||||
|
|
|
@ -19,6 +19,19 @@ public static class Generator {
|
|||
|
||||
w("using System;");
|
||||
w($"{singleHeader}");
|
||||
foreach (var type in types) {
|
||||
var name = type.Key;
|
||||
var kind = type.Value.Item1;
|
||||
var components = type.Value.Item2;
|
||||
switch (kind) {
|
||||
case Kind.Record:
|
||||
w.RecordUsing(header, footer, qualifier, name, @components);
|
||||
break;
|
||||
case Kind.Variant:
|
||||
w.VariantUsing(header, footer, qualifier, name, @components);
|
||||
break;
|
||||
}
|
||||
}
|
||||
w("");
|
||||
foreach (var type in types) {
|
||||
var name = type.Key;
|
||||
|
|
|
@ -6,6 +6,15 @@ using System.Linq;
|
|||
using Record = System.Collections.Immutable.ImmutableDictionary<string, string>;
|
||||
|
||||
public static class RecordGenerator {
|
||||
private static void NewExampleComment(this Action<string> w, string qualifier, string name, Record record) {
|
||||
w($" /* To create an instance of {name}, write:");
|
||||
w($" new {name}(");
|
||||
w(String.Join(",\n", record.Select(@field =>
|
||||
$" {@field.Key}: new {@field.Value}(…)")));
|
||||
w($" )");
|
||||
w($" */");
|
||||
}
|
||||
|
||||
private static void Fields(this Action<string> w, string qualifier, string name, Record record) {
|
||||
foreach (var @field in record) {
|
||||
var F = @field.Key;
|
||||
|
@ -69,7 +78,9 @@ public static class RecordGenerator {
|
|||
private static void Lenses(this Action<string> w, string qualifier, string name, Record record) {
|
||||
w($" public sealed class Lens<Whole> : ILens<{name}, Whole> {{");
|
||||
w($" public readonly System.Func<{name}, Whole> wrap;");
|
||||
w($" public readonly {name} oldHole;");
|
||||
w($" private readonly {name} oldHole;");
|
||||
w($"");
|
||||
w($" public {name} value {{ get => oldHole; }}");
|
||||
w($"");
|
||||
w($" public Lens(System.Func<{name}, Whole> wrap, {name} oldHole) {{");
|
||||
w($" this.wrap = wrap;");
|
||||
|
@ -84,7 +95,8 @@ public static class RecordGenerator {
|
|||
w($" => oldHole.{F}.ChainLens(");
|
||||
w($" value => wrap(oldHole.With{caseF}(value)));");
|
||||
}
|
||||
w($" public Whole Update(Func<{name}, {name}> update) => wrap(update(oldHole));");
|
||||
w($" public Whole Update(Func<{name}, {name}> update)");
|
||||
w($" => wrap(update(oldHole));");
|
||||
w($" }}");
|
||||
}
|
||||
|
||||
|
@ -106,10 +118,42 @@ public static class RecordGenerator {
|
|||
w($" }}");
|
||||
}
|
||||
|
||||
private static void LensExtensionMethods(this Action<string> w, string qualifier, string name, Record record) {
|
||||
w($" public static class {name}LensExtensionMethods {{");
|
||||
foreach (var @field in record) {
|
||||
var F = @field.Key;
|
||||
var noAtF = F.StartsWith("@") ? F.Substring(1) : F;
|
||||
var caseF = Char.ToUpper(noAtF[0]) + noAtF.Substring(1);
|
||||
var Ty = @field.Value;
|
||||
// same as {name}.Lens but as extension mehtods (should
|
||||
// be extension properties once C# supports those) to
|
||||
// be applied to instances of ILens<{name}, Whole>
|
||||
w($" public static ILens<{Ty}, Whole>");
|
||||
w($" {caseF}<Whole>(");
|
||||
w($" this ILens<{qualifier}{name}, Whole> self)");
|
||||
w($" => self.value.{F}.ChainLens(");
|
||||
w($" value => self.Update(oldHole => oldHole.With{caseF}(value)));");
|
||||
}
|
||||
w($" }}");
|
||||
}
|
||||
|
||||
public static void Record(this Action<string> w, string header, string footer, string qualifier, string name, Record record) {
|
||||
w($"{header}");
|
||||
w("");
|
||||
w.NewExampleComment(qualifier, name, record);
|
||||
w("");
|
||||
w.RecordClass(qualifier, name, record);
|
||||
w($"{footer}");
|
||||
w.LensExtensionMethods(qualifier, name, record);
|
||||
}
|
||||
|
||||
private static void QualifierAliases(this Action<string> w, string qualifier, string name, Record record) {
|
||||
if (qualifier != "") {
|
||||
w($"using {name} = {qualifier}{name};");
|
||||
}
|
||||
}
|
||||
|
||||
public static void RecordUsing(this Action<string> w, string header, string footer, string qualifier, string name, Record record) {
|
||||
w.QualifierAliases(qualifier, name, record);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -185,8 +185,20 @@ public static class VariantGenerator {
|
|||
w($"{header}");
|
||||
w($"");
|
||||
w.MatchExampleComment(qualifier, name, variant);
|
||||
w($"");
|
||||
w.VariantClass(qualifier, name, variant);
|
||||
w($"");
|
||||
w.ExtensionMethods(qualifier, name, variant);
|
||||
w($"{footer}");
|
||||
}
|
||||
|
||||
private static void QualifierAliases(this Action<string> w, string qualifier, string name, Variant variant) {
|
||||
if (qualifier != "") {
|
||||
w($"using {name} = {qualifier}{name};");
|
||||
}
|
||||
}
|
||||
|
||||
public static void VariantUsing(this Action<string> w, string header, string footer, string qualifier, string name, Variant variant) {
|
||||
w.QualifierAliases(qualifier, name, variant);
|
||||
}
|
||||
}
|
|
@ -7,6 +7,11 @@ public class ImmutableDefaultDictionary<TKey, TValue> : IEnumerable<KeyValuePair
|
|||
public readonly TValue defaultValue;
|
||||
public readonly ImmutableDictionary<TKey, TValue> dictionary;
|
||||
|
||||
public ImmutableDefaultDictionary(TValue defaultValue) {
|
||||
this.defaultValue = defaultValue;
|
||||
this.dictionary = ImmutableDictionary<TKey, TValue>.Empty;
|
||||
}
|
||||
|
||||
public ImmutableDefaultDictionary(TValue defaultValue, ImmutableDictionary<TKey, TValue> dictionary) {
|
||||
this.defaultValue = defaultValue;
|
||||
this.dictionary = dictionary;
|
||||
|
@ -16,9 +21,15 @@ public class ImmutableDefaultDictionary<TKey, TValue> : IEnumerable<KeyValuePair
|
|||
get => dictionary.GetOrDefault(key, defaultValue);
|
||||
}
|
||||
|
||||
public ImmutableDefaultDictionary<TKey, TValue> With(TKey key, TValue value)
|
||||
public ImmutableDefaultDictionary<TKey, TValue> Add(TKey key, TValue value)
|
||||
=> new ImmutableDefaultDictionary<TKey, TValue>(defaultValue, dictionary.Add(key, value));
|
||||
|
||||
public ImmutableDefaultDictionary<TKey, TValue> SetItem(TKey key, TValue value)
|
||||
=> new ImmutableDefaultDictionary<TKey, TValue>(defaultValue, dictionary.SetItem(key, value));
|
||||
|
||||
public ImmutableDefaultDictionary<TKey, TValue> Remove(TKey key)
|
||||
=> new ImmutableDefaultDictionary<TKey, TValue>(defaultValue, dictionary.Remove(key));
|
||||
|
||||
public IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator() => dictionary.GetEnumerator();
|
||||
|
||||
IEnumerator IEnumerable.GetEnumerator() => dictionary.GetEnumerator();
|
||||
|
|
|
@ -1,9 +1,8 @@
|
|||
// Code quality of this file: low.
|
||||
|
||||
using System;
|
||||
using System.Collections.Immutable;
|
||||
|
||||
public interface ILens<Hole, Whole> {
|
||||
Hole value { get; }
|
||||
Whole Update(Func<Hole, Hole> update);
|
||||
}
|
||||
|
||||
|
@ -14,12 +13,6 @@ public static class LensExtensionMethods {
|
|||
public static Whole Cons<T, Whole>(this ILens<ImmutableList<T>, Whole> lens, T value)
|
||||
=> lens.Update(oldHole => oldHole.Cons(value));
|
||||
|
||||
public static ImmutableListLens<T, Whole>
|
||||
ChainLens<T, Whole>(
|
||||
this ImmutableList<T> hole,
|
||||
System.Func<ImmutableList<T>, Whole> wrap)
|
||||
=> new ImmutableListLens<T, Whole>(wrap: wrap, oldHole: hole);
|
||||
|
||||
public static ILens<string, Whole> ChainLens<Whole>(this string hole, System.Func<string, Whole> wrap) => new LeafLens<string, Whole>(wrap: wrap, oldHole: hole);
|
||||
|
||||
public static ILens<Func<GraphemeCluster,bool>, Whole> ChainLens<Whole>(this Func<GraphemeCluster,bool> hole, System.Func<Func<GraphemeCluster,bool>, Whole> wrap) => new LeafLens<Func<GraphemeCluster,bool>, Whole>(wrap: wrap, oldHole: hole);
|
||||
|
|
86
Utils/Lens/ImmutableDefaultDictionaryLens.cs
Normal file
86
Utils/Lens/ImmutableDefaultDictionaryLens.cs
Normal file
|
@ -0,0 +1,86 @@
|
|||
// Code quality of this file: medium.
|
||||
|
||||
using System;
|
||||
using System.Collections.Immutable;
|
||||
|
||||
public sealed class ImmutableDefaultDictionaryValueLens<TKey, TValue, Whole> : ILens<TValue, Whole> {
|
||||
public readonly Func<ImmutableDefaultDictionary<TKey, TValue>, Whole> wrap;
|
||||
|
||||
private readonly ImmutableDefaultDictionary<TKey, TValue> oldDictionary;
|
||||
|
||||
private readonly TKey oldKey;
|
||||
|
||||
public TValue value { get => oldDictionary[oldKey]; }
|
||||
|
||||
public ImmutableDefaultDictionaryValueLens(Func<ImmutableDefaultDictionary<TKey, TValue>, Whole> wrap, ImmutableDefaultDictionary<TKey, TValue> oldDictionary, TKey oldKey) {
|
||||
// TODO: check that key exists.
|
||||
this.wrap = wrap;
|
||||
this.oldDictionary = oldDictionary;
|
||||
this.oldKey = oldKey;
|
||||
}
|
||||
|
||||
// Put methods with the following signature here to focus on sub-parts of the list as needed.
|
||||
// public ILens<ImmutableDefaultDictionary<T>,Whole> sub-part => oldHole.sub-part.ChainLens(value => oldHole.with-sub-part(value));
|
||||
|
||||
public Whole Update(Func<TValue, TValue> update) {
|
||||
var oldValue = oldDictionary[oldKey];
|
||||
return wrap(oldDictionary.SetItem(oldKey, update(oldValue)));
|
||||
}
|
||||
|
||||
public ImmutableDefaultDictionaryValueLens<TKey, TValue, Whole> UpdateKey(Func<TKey, TKey> update) {
|
||||
var newKey = update(oldKey);
|
||||
return new ImmutableDefaultDictionaryValueLens<TKey, TValue, Whole>(
|
||||
wrap,
|
||||
oldDictionary.Remove(oldKey).Add(newKey, oldDictionary[oldKey]),
|
||||
newKey);
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class ImmutableDefaultDictionaryLens<TKey, TValue, Whole> : ILens<ImmutableDefaultDictionary<TKey, TValue>, Whole> {
|
||||
public readonly Func<ImmutableDefaultDictionary<TKey, TValue>, Whole> wrap;
|
||||
private readonly ImmutableDefaultDictionary<TKey, TValue> oldHole;
|
||||
|
||||
public ImmutableDefaultDictionary<TKey, TValue> value { get => oldHole; }
|
||||
|
||||
public ImmutableDefaultDictionaryLens(Func<ImmutableDefaultDictionary<TKey, TValue>, Whole> wrap, ImmutableDefaultDictionary<TKey, TValue> oldHole) {
|
||||
// TODO: check that key exists.
|
||||
this.wrap = wrap;
|
||||
this.oldHole = oldHole;
|
||||
}
|
||||
|
||||
// Put methods with the following signature here to focus on sub-parts of the list as needed.
|
||||
public ImmutableDefaultDictionaryValueLens<TKey, TValue, Whole> this[TKey key] {
|
||||
get => new ImmutableDefaultDictionaryValueLens<TKey, TValue, Whole>(wrap, oldHole, key);
|
||||
}
|
||||
|
||||
public Whole Update(Func<ImmutableDefaultDictionary<TKey, TValue>, ImmutableDefaultDictionary<TKey, TValue>> update) {
|
||||
return wrap(update(oldHole));
|
||||
}
|
||||
}
|
||||
|
||||
public static class ImmutableDefaultDictionaryLensExtensionMethods {
|
||||
public static ImmutableDefaultDictionaryLens<TKey, TValue, Whole>
|
||||
ChainLens<TKey, TValue, Whole>(
|
||||
this ImmutableDefaultDictionary<TKey, TValue> hole,
|
||||
System.Func<ImmutableDefaultDictionary<TKey, TValue>, Whole> wrap)
|
||||
=> new ImmutableDefaultDictionaryLens<TKey, TValue, Whole>(wrap: wrap, oldHole: hole);
|
||||
|
||||
// TODO: this should be an extension property (once C# supports them)
|
||||
public static ImmutableDefaultDictionaryLens<TKey, TValue, ImmutableDefaultDictionary<TKey, TValue>>
|
||||
lens<TKey, TValue>(
|
||||
this ImmutableDefaultDictionary<TKey, TValue> d)
|
||||
=> d.ChainLens(x => x);
|
||||
|
||||
// this is a shorthand since we don't have extension properties
|
||||
public static ImmutableDefaultDictionaryValueLens<TKey, TValue, ImmutableDefaultDictionary<TKey, TValue>>
|
||||
lens<TKey, TValue>(
|
||||
this ImmutableDefaultDictionary<TKey, TValue> d,
|
||||
TKey key)
|
||||
=> d.lens()[key];
|
||||
|
||||
public static ImmutableDefaultDictionaryValueLens<TKey, TValue, Whole>
|
||||
UpdateKey<TKey, TValue, Whole>(
|
||||
this ImmutableDefaultDictionaryValueLens<TKey, TValue, Whole> lens,
|
||||
TKey newKey)
|
||||
=> lens.UpdateKey(oldKey => newKey);
|
||||
}
|
|
@ -1,63 +0,0 @@
|
|||
using System;
|
||||
using System.Collections.Immutable;
|
||||
|
||||
public sealed class ImmutableDictionaryValueLens<TKey, TValue, Whole> : ILens<TValue, Whole> {
|
||||
public readonly Func<ImmutableDictionary<TKey, TValue>, Whole> wrap;
|
||||
public readonly ImmutableDictionary<TKey, TValue> oldDictionary;
|
||||
public readonly TKey oldKey;
|
||||
|
||||
public ImmutableDictionaryValueLens(Func<ImmutableDictionary<TKey, TValue>, Whole> wrap, ImmutableDictionary<TKey, TValue> oldDictionary, TKey oldKey) {
|
||||
// TODO: check that key exists.
|
||||
this.wrap = wrap;
|
||||
this.oldDictionary = oldDictionary;
|
||||
this.oldKey = oldKey;
|
||||
}
|
||||
|
||||
// Put methods with the following signature here to focus on sub-parts of the list as needed.
|
||||
// public ILens<ImmutableList<T>,Whole> sub-part => oldHole.sub-part.ChainLens(value => oldHole.with-sub-part(value));
|
||||
|
||||
public Whole Update(Func<TValue, TValue> update) {
|
||||
var oldValue = oldDictionary[oldKey];
|
||||
return wrap(oldDictionary.SetItem(oldKey, update(oldValue)));
|
||||
}
|
||||
|
||||
public ImmutableDictionaryValueLens<TKey, TValue, Whole> UpdateKey(Func<TKey, TKey> update) {
|
||||
var newKey = update(oldKey);
|
||||
return new ImmutableDictionaryValueLens<TKey, TValue, Whole>(
|
||||
wrap,
|
||||
oldDictionary.Remove(oldKey).Add(newKey, oldDictionary[oldKey]),
|
||||
newKey);
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class ImmutableDictionaryLens<TKey, TValue, Whole> : ILens<ImmutableDictionary<TKey, TValue>, Whole> {
|
||||
public readonly Func<ImmutableDictionary<TKey, TValue>, Whole> wrap;
|
||||
public readonly ImmutableDictionary<TKey, TValue> oldHole;
|
||||
|
||||
public ImmutableDictionaryLens(Func<ImmutableDictionary<TKey, TValue>, Whole> wrap, ImmutableDictionary<TKey, TValue> oldHole) {
|
||||
// TODO: check that key exists.
|
||||
this.wrap = wrap;
|
||||
this.oldHole = oldHole;
|
||||
}
|
||||
|
||||
// Put methods with the following signature here to focus on sub-parts of the list as needed.
|
||||
public ImmutableDictionaryValueLens<TKey, TValue, Whole> this[TKey key] {
|
||||
get => new ImmutableDictionaryValueLens<TKey, TValue, Whole>(wrap, oldHole, key);
|
||||
}
|
||||
|
||||
public Whole Update(Func<ImmutableDictionary<TKey, TValue>, ImmutableDictionary<TKey, TValue>> update) {
|
||||
return wrap(update(oldHole));
|
||||
}
|
||||
}
|
||||
|
||||
public static class ImmutableDictionaryLensExtensionMethods {
|
||||
public static ImmutableDictionaryLens<TKey, TValue, ImmutableDictionary<TKey, TValue>> lens<TKey, TValue>(this ImmutableDictionary<TKey, TValue> d)
|
||||
=> new ImmutableDictionaryLens<TKey, TValue, ImmutableDictionary<TKey, TValue>>(x => x, d);
|
||||
|
||||
public static ImmutableDictionaryValueLens<TKey, TValue, Whole> UpdateKey<TKey, TValue, Whole, Whole>(this ImmutableDictionaryValueLens<TKey, TValue, Whole> lens, TKey newKey)
|
||||
=> lens.UpdateKey(oldKey => newKey);
|
||||
|
||||
// This would need an IFocusable<TValue> constraint which is hard to get
|
||||
//public static ILens<ImmutableDictionary<TKey, ?>, Whole> ChainLens<TKey, Whole>(this ImmutableDictionary<TKey, ?> hole, System.Func<ImmutableDictionary<TKey, ?>, Whole> wrap)
|
||||
// => new ImmutableDictionaryLens<TKey, ?, Whole>(wrap: wrap, oldHole: hole);
|
||||
}
|
|
@ -3,7 +3,9 @@ using System.Collections.Immutable;
|
|||
|
||||
public sealed class ImmutableListLens<T, Whole> : ILens<ImmutableList<T>, Whole> {
|
||||
public readonly Func<ImmutableList<T>, Whole> wrap;
|
||||
public readonly ImmutableList<T> oldHole;
|
||||
private readonly ImmutableList<T> oldHole;
|
||||
|
||||
public ImmutableList<T> value { get => oldHole; }
|
||||
|
||||
public ImmutableListLens(Func<ImmutableList<T>, Whole> wrap, ImmutableList<T> oldHole) {
|
||||
this.wrap = wrap;
|
||||
|
@ -11,12 +13,21 @@ public sealed class ImmutableListLens<T, Whole> : ILens<ImmutableList<T>, Whole>
|
|||
}
|
||||
|
||||
// Put methods with the following signature here to focus on sub-parts of the list as needed.
|
||||
// public ILens<ImmutableList<T>,Whole> sub-part => oldHole.sub-part.ChainLens(value => oldHole.with-sub-part(value));
|
||||
// public ILens<ImmutableList<T>,Whole> sub-part
|
||||
// => oldHole.sub-part.ChainLens(value => oldHole.with-sub-part(value));
|
||||
|
||||
public Whole Update(Func<ImmutableList<T>, ImmutableList<T>> update) => wrap(update(oldHole));
|
||||
}
|
||||
|
||||
public static class ImmutableListLensExtensionMethods {
|
||||
public static ILens<ImmutableList<string>, Whole> ChainLens<Whole>(this ImmutableList<string> hole, System.Func<ImmutableList<string>, Whole> wrap)
|
||||
=> new ImmutableListLens<string, Whole>(wrap: wrap, oldHole: hole);
|
||||
}
|
||||
public static ImmutableListLens<T, Whole>
|
||||
ChainLens<T, Whole>(
|
||||
this ImmutableList<T> hole,
|
||||
System.Func<ImmutableList<T>, Whole> wrap)
|
||||
=> new ImmutableListLens<T, Whole>(wrap: wrap, oldHole: hole);
|
||||
|
||||
public static ImmutableListLens<T, ImmutableList<T>>
|
||||
lens<T>(
|
||||
this ImmutableList<T> d)
|
||||
=> d.ChainLens(x => x);
|
||||
}
|
||||
|
|
|
@ -5,7 +5,9 @@ using System.Collections.Immutable;
|
|||
// interesting to further focus.
|
||||
public sealed class LeafLens<T, Whole> : ILens<T, Whole> {
|
||||
public readonly System.Func<T, Whole> wrap;
|
||||
public readonly T oldHole;
|
||||
private readonly T oldHole;
|
||||
|
||||
public T value { get => oldHole; }
|
||||
|
||||
public LeafLens(System.Func<T, Whole> wrap, T oldHole) {
|
||||
this.wrap = wrap;
|
||||
|
|
Loading…
Reference in New Issue
Block a user