2013-10-15 6 views
1

Итак, я хочу, чтобы построить выражение вычисления пользовательского, который позволил бы мне превратить это -Как преобразовать выражение прямой трубы в выражение вычисления?

testWorld |> 
    subscribe ClickTestButtonAddress [] addBoxes |> 
    addScreen testScreen TestScreenAddress |> 
    setP (Some TestScreenAddress) World.optActiveScreenAddress |> 
    addGroup testGroup TestGroupAddress |> 
    addEntityGuiLabel (testLabelGuiEntity, testLabelGui, testLabel) TestLabelAddress |> 
    addEntityGuiButton (testButtonGuiEntity, testButtonGui, testButton) TestButtonAddress |> 
    addEntityActorBlock (testFloorActorEntity, testFloorActor, testFloor) TestFloorAddress |> 
    (let hintRenderingPackageUse = HintRenderingPackageUse { FileName = "AssetGraph.xml"; PackageName = "Misc"; HRPU =() } 
    fun world -> { world with RenderMessages = hintRenderingPackageUse :: world.RenderMessages }) |> 
    (let hintAudioPackageUse = HintAudioPackageUse { FileName = "AssetGraph.xml"; PackageName = "Misc"; HAPU =() } 
    fun world -> { world with AudioMessages = hintAudioPackageUse :: world.AudioMessages }) 

во что-то вроде этого -

fwd { 
    do! subscribe ClickTestButtonAddress [] addBoxes 
    do! addScreen testScreen TestScreenAddress 
    do! setP (Some TestScreenAddress) World.optActiveScreenAddress 
    do! addGroup testGroup TestGroupAddress 
    do! addEntityGuiLabel (testLabelGuiEntity, testLabelGui, testLabel) TestLabelAddress 
    do! addEntityGuiButton (testButtonGuiEntity, testButtonGui, testButton) TestButtonAddress 
    do! addEntityActorBlock (testFloorActorEntity, testFloorActor, testFloor) TestFloorAddress 
    let hintRenderingPackageUse = HintRenderingPackageUse { FileName = "AssetGraph.xml"; PackageName = "Misc"; HRPU =() } 
    do! fun world -> { world with RenderMessages = hintRenderingPackageUse :: world.RenderMessages } 
    let hintAudioPackageUse = HintAudioPackageUse { FileName = "AssetGraph.xml"; PackageName = "Misc"; HAPU =() } 
    do! fun world -> { world with AudioMessages = hintAudioPackageUse :: world.AudioMessages }} 
    <| runFwd testWorld 

возможно, или близко к чему это возможно? Если да, то какой подход можно было бы предпринять? Это монада или что-то меньшее?

+1

Просто интересно, что было бы полезно использовать выражения вычислений? (примечание конвейерной обработки выглядит хорошо для меня ...) –

+0

Проще говоря, возможность устанавливать контрольные точки для каждой отдельной операции. Трубопровод один практически невосприимчив, AFAICT. По правде говоря, мое предпочтение было бы для VS, чтобы включить точку останова внутри конвейера, но я этого не вижу.Помимо всего этого, я хочу, возможно, добавить некоторые пользовательские операторы CE. В конечном итоге я пытаюсь создать небольшое выражение выражения для сценариев на уровне типа World. –

+0

Конечно, в моем комментарии предполагается, что есть какой-то способ вывести текущий мир из отладчика ... Может быть, не было бы :(... Может, мне стоит вернуться к нормальному стандарту let-based? –

ответ

6

Может быть, я должен просто вернуться к выполнению этого -

let tw_ = testWorld 
let tw_ = subscribe ClickTestButtonAddress [] addBoxes tw_ 
let tw_ = addScreen testScreen TestScreenAddress tw_ 
let tw_ = setP (Some TestScreenAddress) World.optActiveScreenAddress tw_ 
let tw_ = addGroup testGroup TestGroupAddress tw_ 
let tw_ = addEntityGuiLabel (testLabelGuiEntity, testLabelGui, testLabel) TestLabelAddress tw_ 
let tw_ = addEntityGuiButton (testButtonGuiEntity, testButtonGui, testButton) TestButtonAddress tw_ 
let tw_ = addEntityActorBlock (testFloorActorEntity, testFloorActor, testFloor) TestFloorAddress tw_ 
let tw_ = { tw_ with RenderMessages = hintRenderingPackageUse :: tw_.RenderMessages } 
{ tw_ with AudioMessages = hintAudioPackageUse :: tw_.AudioMessages } 

Это отлаживает отлично (вы можете найти все предыдущие версии tw_ в окне Autos и может активизировать отладку по каждой операции), и это не слишком Довольный, я полагаю.

+0

как я мог не видеть это. Я имею в виду. не будет служить вам лучше здесь. Думаю, – nicolas

1

Для распространения монадического состояния вам понадобится let!.

Итак, у вас уже есть монада: это простой старый let, который берет текущие привязки, добавляет новый и передает его при последующих вычислениях!

2

Если вы используете ExtCore библиотеку (доступны на NuGet), она предоставляет оператору под названием tap, который специально предусмотрен для отладки конвейерных выражений. Вы используете его, «постукивая» по вашему конвейеру, который применяет функцию действия (возвращающую unit) к значению в какой-то момент в конвейере, затем значение передается, чтобы он продолжал протекать по конвейеру, как ожидалось.

Например:

testWorld 
|> subscribe ClickTestButtonAddress [] addBoxes 
|> addScreen testScreen TestScreenAddress 
// Check to see if the screen was added correctly 
|> tap (fun world -> 
    // TODO : Insert code to check if the screen was added. 
    // Or, put some dummy code here so you can set a breakpoint 
    // on it to inspect 'world' in the debugger. 
    ()) 
|> setP (Some TestScreenAddress) World.optActiveScreenAddress 
|> addGroup testGroup TestGroupAddress 
|> addEntityGuiLabel (testLabelGuiEntity, testLabelGui, testLabel) TestLabelAddress 
|> addEntityGuiButton (testButtonGuiEntity, testButtonGui, testButton) TestButtonAddress 
|> addEntityActorBlock (testFloorActorEntity, testFloorActor, testFloor) TestFloorAddress 
|> (let hintRenderingPackageUse = HintRenderingPackageUse { FileName = "AssetGraph.xml"; PackageName = "Misc"; HRPU =() } 
    fun world -> { world with RenderMessages = hintRenderingPackageUse :: world.RenderMessages }) 
|> (let hintAudioPackageUse = HintAudioPackageUse { FileName = "AssetGraph.xml"; PackageName = "Misc"; HAPU =() } 
    fun world -> { world with AudioMessages = hintAudioPackageUse :: world.AudioMessages }) 

Связанная функция, tapAssert, может быть использована для вставки отладочных утверждений в ваш трубопровод.

+0

Я ценю это предложение, но мне действительно нужно иметь возможность вставлять точки останова без перезапуска программы. –

2

Государство или писатель Монада могут быть полезны, но если вы хотите использовать отладчик, забыть о Монадах, это еще хуже. Одна вещь, которую вы можете сделать, это переопределить оператор конвейера так:

let (|>) a b = printfn "Value is: %A" a; b a 

5 
    |> ((+) 40) 
    |> string 
    |> Seq.singleton 
    |> Seq.toArray 

Вы увидите:

Value is: 5 
Value is: 45 
Value is: "45" 
Value is: seq ["45"] 
val it : string [] = [|"45"|] 

Или вы можете вместо печати, накапливать результаты в изменяемом списке объектов.

let mutable results = [] : obj list 
let (|>) a b = 
    results <- results @ [box a] // or set a breakpoint here 
    b a 
... 
val mutable results : obj list = [5; 45; "45"; <seq>] 

Это почти как писательская монада.

Но если вы определенно хотите использовать отладчик (это не мой любимый инструмент), вы используете решение с let, но вам нужно изменить свой код, и вы потеряете трубку вперед. В этом случае было бы лучше добавьте точку останова в тело функции (|>).

+0

Хе-хе, это круто, но я определенно не хочу печатать мир :) В защиту монад, по крайней мере, вы можете поставить точку прерывания на каждую операцию - просто не пытайтесь отлаживать шаг :) –

+0

Вы также можете установить точку останова в теле переопределения этого оператора. Просто сделайте это многострочным, я добавил комментарий в последнем примере. – Gustavo

 Смежные вопросы

  • Нет связанных вопросов^_^