Я учил себя F # в последнее время, и я родом из императивного (C++/C#) фона. В качестве упражнения я работал над функциями, которые могут делать вещи с помощью матриц, например, добавлять, умножать, получать детерминанты и т. Д. В этом отношении все идет хорошо, но я считаю, что, возможно, я не принимаю наилучших решений, когда это касается обработки недействительные входы, например:F #: Some, None или Exception?
// I want to multiply two matrices
let mult m1 m2 =
let sizeOK = validateDims m1 m2
// Here is where I am running to conceptual trouble:
// In a C# world, I would throw an exception.
if !sizeOK then
raise (InvalidOperationException("bad dimensions!")
else
doWork m1 m2
Так что, хотя это технически работает, подходит ли это для функционального языка? Это в духе функционального программирования? Или это больше смысла переписывать его как:
let mult m1 m2 =
let sizeOK = validateDims m1 m2
if !sizeOK then
None
else
Some doWork m1 m2
В этом случае я возвращаю вариант, который добавляет дополнительный слой вокруг матрицы, но я мог бы также использовать результаты функции, даже в отказе случаев (Нет) с сопоставлением с образцом и т. д. в какой-то более поздний момент в программе. Итак, есть ли наилучшая практика для этих типов сценариев? Что бы сделал функциональный программист?
Я считаю, что последнее больше похоже на «дух» FP. Возможно, вы захотите взглянуть на монаду Maybe, а также на общий подход к работе с плохими входами. –
Как сказано в ответе, я также часто реализую две функции, которые бросают ошибки и идентичную функцию try, которая возвращает опцию/выбор вместо метания. то я использую тот, который делает мой последний код более привлекательным :) для упрощения обработки параметров/выбора вы можете прочитать «железнодорожное ориентированное программирование»: http://fsharpforfunandprofit.com/posts/recipe-part2/ – stmax