Skip to content

Commit f28eec3

Browse files
committed
Non-working code for CE PoC to combined custom operations with standard CE
1 parent 349124b commit f28eec3

File tree

2 files changed

+219
-1
lines changed

2 files changed

+219
-1
lines changed
Lines changed: 217 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,217 @@
1+
namespace TaskSeq.Tests
2+
3+
open Xunit
4+
open FsUnit.Xunit
5+
6+
open FSharp.Control
7+
8+
9+
module CEs =
10+
11+
type M<'T, 'Vars> = {
12+
Name: string option
13+
IsMember: bool option
14+
IsMember2: bool // confirming that shape of the container is not restricted, just need clear default the CE understands
15+
Members: 'T list
16+
Variables: 'Vars
17+
}
18+
19+
type M<'T> = M<'T, unit>
20+
21+
type CE() =
22+
23+
member _.Zero() : M<'T> = {
24+
Name = None
25+
IsMember = None
26+
IsMember2 = false
27+
Members = []
28+
Variables = ()
29+
}
30+
31+
member _.Combine(model1: M<'T>, model2: M<'T>) : M<'T> =
32+
let newName =
33+
match model2.Name with
34+
| None -> model1.Name
35+
| res -> res
36+
37+
let newIsMember =
38+
match model2.IsMember with
39+
| None -> model1.IsMember
40+
| res -> res
41+
42+
let newIsMember2 =
43+
match model2.IsMember2 with
44+
| true -> true
45+
| res -> res
46+
47+
{
48+
Name = newName
49+
IsMember = newIsMember
50+
IsMember2 = newIsMember2
51+
Members = List.append model1.Members model2.Members
52+
Variables = ()
53+
}
54+
55+
member _.Delay(f) : M<'T, 'Vars> = f ()
56+
57+
member _.Run(model: M<'T, 'Vars>) : M<'T> = {
58+
Name = model.Name
59+
IsMember = model.IsMember
60+
IsMember2 = model.IsMember2
61+
Members = model.Members
62+
Variables = ()
63+
}
64+
65+
member this.For(methods, f) : M<'T> =
66+
let methodList = Seq.toList methods
67+
68+
match methodList with
69+
| [] -> this.Zero()
70+
| [ x ] -> f (x)
71+
| head :: tail ->
72+
let mutable headResult = f (head)
73+
74+
for x in tail do
75+
headResult <- this.Combine(headResult, f (x))
76+
77+
headResult
78+
79+
member _.Yield(item: 'T) : M<'T> = {
80+
Name = None
81+
IsMember = None
82+
IsMember2 = false
83+
Members = [ item ]
84+
Variables = ()
85+
}
86+
87+
// Only for packing/unpacking the implicit variable space
88+
member _.Bind(model1: M<'T, 'Vars>, f: ('Vars -> M<'T>)) : M<'T> =
89+
let model2 = f model1.Variables
90+
91+
let newName =
92+
match model2.Name with
93+
| None -> model1.Name
94+
| res -> res
95+
96+
let newIsMember =
97+
match model2.IsMember with
98+
| None -> model1.IsMember
99+
| res -> res
100+
101+
let newIsMember2 =
102+
match model2.IsMember2 with
103+
| true -> true
104+
| res -> res
105+
106+
{
107+
Name = newName
108+
IsMember = newIsMember
109+
IsMember2 = newIsMember2
110+
Members = model1.Members @ model2.Members
111+
Variables = model2.Variables
112+
}
113+
114+
// Only for packing/unpacking the implicit variable space
115+
member _.Return(varspace: 'Vars) : M<'T, 'Vars> = {
116+
Name = None
117+
IsMember = None
118+
IsMember2 = false
119+
Members = []
120+
Variables = varspace
121+
}
122+
123+
[<CustomOperation("Name", MaintainsVariableSpaceUsingBind = true)>]
124+
member _.setName(model: M<'T, 'Vars>, [<ProjectionParameter>] name: ('Vars -> string)) : M<'T, 'Vars> = {
125+
model with
126+
Name = Some(name model.Variables)
127+
}
128+
129+
[<CustomOperation("IsMember", MaintainsVariableSpaceUsingBind = true)>]
130+
member _.setIsMember(model: M<'T, 'Vars>, [<ProjectionParameter>] isMember: ('Vars -> bool)) : M<'T, 'Vars> = {
131+
model with
132+
IsMember = Some(isMember model.Variables)
133+
}
134+
135+
// We can skip
136+
[<CustomOperation("IsMember2", MaintainsVariableSpaceUsingBind = true)>]
137+
member _.setIsMember2(model: M<'T, 'Vars>, [<ProjectionParameter>] isMember: ('Vars -> bool)) : M<'T, 'Vars> = {
138+
model with
139+
IsMember2 = isMember model.Variables
140+
}
141+
142+
[<CustomOperation("Member", MaintainsVariableSpaceUsingBind = true)>]
143+
member _.addMember(model: M<'T, 'Vars>, [<ProjectionParameter>] item: ('Vars -> 'T)) : M<'T, 'Vars> = {
144+
model with
145+
Members = List.append model.Members [ item model.Variables ]
146+
}
147+
148+
// Note, using ParamArray doesn't work in conjunction with ProjectionParameter
149+
[<CustomOperation("Members", MaintainsVariableSpaceUsingBind = true)>]
150+
member _.addMembers(model: M<'T, 'Vars>, [<ProjectionParameter>] items: ('Vars -> 'T list)) : M<'T, 'Vars> = {
151+
model with
152+
Members = List.append model.Members (items model.Variables)
153+
}
154+
155+
let ce = CE()
156+
157+
module Test =
158+
let x: M<double> = ce { Name "Fred" }
159+
160+
let x2: M<double> = ce {
161+
Name "Fred"
162+
IsMember true
163+
IsMember true
164+
IsMember2 true // Note, I can call this twice without compiler error, but not Name in z5
165+
IsMember2 true
166+
}
167+
168+
let y = ce { 42 }
169+
170+
let z1 = ce { Member 42 }
171+
172+
let z2 = ce { Members [ 41; 42 ] }
173+
174+
let z3 = ce {
175+
Name "Fred"
176+
42
177+
}
178+
179+
let z4 = ce {
180+
Member 41
181+
Member 42
182+
}
183+
184+
let z5: M<double> = ce {
185+
Name "a"
186+
Name "b"
187+
//42 // removing this line results in compiler error
188+
}
189+
190+
let z6: M<double> = ce {
191+
let x = 1
192+
let y = 2
193+
let z = 3
194+
let! foo = Unchecked.defaultof<M<double>>
195+
Name "a"
196+
Member 4.0
197+
}
198+
199+
let z7: M<double> = ce {
200+
let x = "a"
201+
Name(x + "b")
202+
Member 4.0
203+
}
204+
205+
let z8: M<double> = ce {
206+
let x1 = 1.0
207+
let y2 = 2.0
208+
Member(x1 + 3.0)
209+
Member(y2 + 4.0)
210+
}
211+
212+
let z9 = ce {
213+
let x = 1.0
214+
Members [ 42.3; 43.1 + x ]
215+
}
216+
//let empty =
217+
// ce { }

src/FSharp.Control.TaskSeq.Test/FSharp.Control.TaskSeq.Test.fsproj

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
<Project Sdk="Microsoft.NET.Sdk">
1+
<Project Sdk="Microsoft.NET.Sdk">
22

33
<PropertyGroup>
44
<TargetFramework>net6.0</TargetFramework>
@@ -8,6 +8,7 @@
88
<Compile Include="AssemblyInfo.fs" />
99
<Compile Include="Nunit.Extensions.fs" />
1010
<Compile Include="TestUtils.fs" />
11+
<Compile Include="CEPoC.fs" />
1112
<Compile Include="TaskSeq.Append.Tests.fs" />
1213
<Compile Include="TaskSeq.Cast.Tests.fs" />
1314
<Compile Include="TaskSeq.Choose.Tests.fs" />

0 commit comments

Comments
 (0)