我是一个相对较新的F#程序员,似乎每次我修复代码中的一个问题时,都会出现另一个问题,所以我的问题在转置递归函数内部,我想在它内部运行一个if-else语句来检查输入是否真的有效,但这会出错,我不知道为什么或如何修复它。
我已经有一个问题的题目和题目非常相似,但由于各种原因,我被告知要做一个新问题,而不是编辑旧问题。
type Result<'T,'TError> =
| Ok of 'T
| Error of 'TError
let isValidTBL list =
match List.map List.length list |> List.distinct |> List.length with
| 1 -> true
| _ -> false
let Column_1 list =
if List.exists List.isEmpty list then [] // return empty list
else
list |> List.map List.head
let Column_2 list =
if List.exists List.isEmpty list then
Error "empty value"
else
list |> List.map List.tail |> Ok
let rec transpose list = [
if (isValidTBL list = false) then Error "Invalid Table"
else
match list with
| []::list -> ()
| list ->
yield Column_1 list
yield! transpose (Column_2 list) ]
警告FS0020:此表达式的结果类型为"result<"a、 字符串>'并且被隐式地忽略。请考虑使用"ignore"显式放弃此值,例如"expr|>ignore",或"let"将结果绑定到名称,例如"let result=expr">
错误FS0001:此表达式的类型应为"列表">
但此处有类型'结果<'b列表列表,字符串>'
提前感谢
关键问题是您试图将Result
与普通F#list
混合。当你在列表理解中时,你只能使用yield
返回值,所以当你写:
let rec transpose list = [
if (isValidTBL list = false) then Error "Invalid Table"
else
yield // (...)
]
带有Error "Invalid table"
的部分不是返回值,而只是您创建然后忽略的值。这一点你可以通过重新排列代码来解决,只在Ok
的情况下开始列表理解:
let rec transpose list =
if (isValidTBL list = false) then Error "Invalid Table"
else Ok [
yield // (...)
]
然而,这也不能解决所有的问题,因为你想对transpose
进行递归调用,如果这也在理解中,那么它就是";太迟了";以返回错误。
你可以在不理解的情况下写这篇文章,但老实说,我认为如果你只使用异常处理错误,这会变得容易得多:
exception InvalidTable
exception EmptyValue
let Column_2 list =
if List.exists List.isEmpty list then raise EmptyValue
else list |> List.map List.tail
let rec transpose list = [
if (isValidTBL list = false) then raise InvalidTable
else
match list with
| []::list -> ()
| list ->
yield Column_1 list
yield! transpose (Column_2 list) ]
您必须确保处理异常,如果在整个项目中使用Result
,则可能希望将它们转换为Error
值,但这样代码会变得更简单。