F#If语句类型不匹配错误



我是一个相对较新的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值,但这样代码会变得更简单。

最新更新