2016-03-21 4 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

Вы видели [Железнодорожное ориентированное программирование] (https://fsharpforfunandprofit.com/posts/recipe-part2/)? –

ответ

9

Для быстрого и грязного раствора, вы всегда можете добавить функцию как этот:

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

Если, например, у вас есть композиции, как это:

[1..10] 
|> List.map string 
|> String.concat "|" 

вы можете вставить tee для достижения побочного эффекта:

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

Это не работает, но может использоваться в крайнем случае, если вам просто нужно посмотреть некоторые промежуточные значения; например для устранения неполадок.

В противном случае для «правильного» функционального решения может быть целесообразным применение State monad. Это позволит вам переносить состояние во время выполнения вычислений. Государство могло бы, например, содержать пользовательские сообщения, собранные по пути ...

Если вы просто хотите «выйти», как только обнаружите, что что-то не так, то Either monad - это подходящий способ пойти ,

+0

Благодарим вас за советы. – demas