2016-03-21 25 views
4

我有一个看起来像这样的代码:如何从多步流水线函数的每一步获得中间结果?

this.GetItemTypeIdsAsListForOneItemTypeIdTreeUpIncludeItemType itemType.AutoincrementedId 
|> Array.map (fun i -> i.AutoincrementedId) 
|> Array.map (BusinessLogic.EntityTypes.getFullSetOfEntityTypeFieldValuesForItemTypeAid item.Autoincrementedid) 
|> Array.fold Array.append [||] 
|> Array.map (fun fv -> { fv with ReferenceAutoId = aid }) 
|> Array.toSeq 
|> Seq.distinctBy (fun fv -> fv.Fieldname) 
|> Seq.toArray 

有时候,这些代码获取不同寻常的结果,我需要解释一下。通常代码中没有错误。数据中有错误。我需要解释为什么这些数据不正确。什么是最好的方式来做到这一点?

我只想看看这个表达式每一步的列表。

喜欢的东西:

func data 
|> func2 && Console.WriteLine 
|> func3 && Console.WriteLine 
.... 

获取输入,将它的两个。将其中一个输出传递给下一个函数,并将第二个输出传递给控制台。

+0

通常代码中没有错误。数据中有错误。我需要解释为什么这些数据不正确。 – demas

+0

您的标题和问题具有误导性。你在调试中寻求帮助,但然后询问如何进行最佳单元测试。我会这样做的方式是将其视为功能组合并分别测试每个功能。如果你的测试是正确的,那么组成这些功能不应该引入任何意想不到的结果,例如错误。把它看作数学的这个,你有函数a + b * c^d-fx/gx。你可以分别测试+, - ,*,/,^和函数f和g。从数学的角度来看,即使它是一个更简单的函数/表达式的组合,你仍然有信心表达式能够工作。 –

+0

你见过[Railway Oriented programming](https://fsharpforfunandprofit.com/posts/recipe-part2/)吗? –

回答

9

对于一个快速和肮脏的解决方案,你可以随时添加一个功能像这样的:

// ('a -> unit) -> 'a -> 'a 
let tee f x = f x; x 

如果,例如,你有这样的组成:

​​

可以插入tee为了实现一个副作用:

[1..10] 
|> List.map string 
|> tee (printfn "%A") 
|> String.concat "|" 

这是不起作用,但可用于捏,如果你只需要看一些中间值;例如进行故障排除

否则,对于“适当”的功能解决方案,可能应用State monad可能是适当的。这将使您能够在执行计算时执行状态。例如,该州可能包含沿途收集的自定义消息...

如果您只是想在您发现有问题时立即“退出”,那么Either monad是适当的方法。

+0

谢谢你的建议。 – demas

相关问题