this question에 대한 후속 질문입니다.이 계산 표현식 빌더가 for for 루프에서 "unit"을 기대하는 이유는 무엇입니까?
사용자 지정 작업을 통해 값을 누적하는 계산 식 작성기를 만들고 동시에 표준 F # 언어 구문을 지원하려고합니다. 간단한 예를 들어 설명하기 위해 F # 목록을 작성하는 계산식을 사용하고 있습니다. kvb와 Daniel의 제안 덕분에 더 나아 갔지만 여전히 for
루프에 문제가 있습니다.
빌더 :
type Items<'a> = Items of 'a list
type ListBuilder() =
member x.Yield(vars) = Items [], vars
member x.Run(l,_) = l
member x.Zero() = Items [],()
member x.Delay f = f()
member x.ReturnFrom f = f
member x.Combine((Items curLeft, _), (Items curRight, vars)) =
(Items (curLeft @ curRight), vars)
member x.Bind(m: Items<'a> * 'v, f: 'v -> Items<'a> * 'o) : Items<'a> * 'o =
let (Items current, vals) = m
x.Combine(m, f vals)
member x.While(guard, body) =
if not (guard()) then
x.Zero()
else
x.Bind(body, fun() -> x.While(guard, body))
member x.TryWith(body, handler) =
try
x.ReturnFrom(body())
with e ->
handler e
member x.TryFinally(body, compensation) =
try
x.ReturnFrom(body())
finally
compensation()
member x.Using(disposable:#System.IDisposable, body) =
let body' = fun() -> body disposable
x.TryFinally(body', fun() ->
match disposable with
| null ->()
| disp -> disp.Dispose())
member x.For(xs:seq<'a>, body) =
x.Using(xs.GetEnumerator(), fun enum ->
x.While(enum.MoveNext, x.Delay(fun() -> body enum.Current)))
[<CustomOperation("add", MaintainsVariableSpace=true)>]
member x.Add((Items current, vars), [<ProjectionParameter>] f) =
Items (current @ [f vars]), vars
[<CustomOperation("addMany", MaintainsVariableSpace=true)>]
member x.AddMany((Items current, vars), [<ProjectionParameter>] f) =
Items (current @ f vars), vars
let listBuilder = ListBuilder()
let build (Items items) = items
이 버전은 같은 내가 전에 할 수 없었던 일, 수 있습니다 :
let stuff =
listBuilder {
let x = 5 * 47
printfn "hey"
add x
addMany [x .. x + 10]
} |> build
는 그러나, 나는 아직이 일에 컴파일러 오류를 받고 있어요 :
let stuff2 =
listBuilder {
for x in 1 .. 50 do
add x
} |> build
이 경우 IDE는 x에 for x in
의 밑줄을 표시하고 "이 식 유형 단위가있을 것으로 예상되었지만 유형은 int입니다. "
루프 변수가 유형 단위 일 것으로 예상되는 이유는 분명하지 않습니다. 분명히 나는 어딘가에 잘못된 메소드 서명을 가지고있다. 나는 필자가 있어야하는 모든 곳에서 누적 된 상태를 넘지 않을 것이라고 생각한다. 그러나 컴파일러 오류는 내가 잘못 된 부분을 좁히는 데 도움이되지 않는다. 모든 제안을 부탁드립니다.
좋아, 그럼 내가 제어 흐름 연산자와 사용자 지정 작업을 혼합하는 데 많은 어려움을 겪고있는 이유를 설명합니다. 컬렉션을 처리하기 위해 몇 가지 추가 사용자 지정 연산자를 추가 할 것입니다. 즉, 루프 부족은 너무 많은 문제가되지 않을 것입니다. 감사. –