F#如何构建匹配和满足类型

时间:2017-06-09 20:22:01

标签: types f# match

我有一个函数archive_lb_files,我希望使用测试函数来删除除一个匹配之外的所有匹配项。我不确定如何纠正存根匹配,所以我没有得到

此表达式应具有类型字符串 - > bool,但这里有类型单位

错误。

以下是代码段,FileMaint.fm.archive_lb_file lb_dir archive_dir fn返回一个bool。

(* Subroutine to process files we fetch from IC, and then need to be uploaded to Munis.  *)
let process_payment_processor_files spool_dir unload_dir paymt_dir report_date =
    use fHLog = FileMaint.fm.open_log_file_out (FileMaint.fm.generate_log_file ())
    // We'll flesh this in when Stratus is installed, and we know the directory names. cmn 5/26/2017
    ignore

let test_print fn =
    printfn "%A" fn

let archive_lb_files lb_dir archive_dir report_date =
    use fHLog = FileMaint.fm.open_log_file_out(FileMaint.fm.generate_log_file () )
    let lb_fnam_template = "*_lockbox.txt"
    let dir_list = Directory.GetFiles(lb_dir, lb_fnam_template)

    for pfn in dir_list do
        let fn = Path.GetFileName(pfn)
        match fn with
        | "cb_lockbox.txt" -> FileMaint.fm.archive_lb_file lb_dir archive_dir fn
        | "ics_lockbox.txt" -> (test_print fn) 
        | "ic_lockbox.txt" -> test_print fn
        | _ -> test_print "does not exist"

在回答答案和评论时,archive_lb_file如何返回一个函数?

(* Moves a file to a unique file name but not including a central directory in between a source and destination. *)
let archive_lb_file lb_path archive_path lockbox_file_name copy_only =
    use fH = new StreamWriter(base_log_file, true)
    let rc =
        try
            if (0 = String.Compare(copy_only, "copy_only")) then
                File.Move((lb_path + lockbox_file_name), archive_path) |> ignore
                fH.WriteLine(generate_time_stamp + ": " + lb_path + lockbox_file_name + " moved to " + archive_path)
            else
                File.Copy((lb_path + lockbox_file_name), archive_path) |> ignore
                fH.WriteLine(generate_time_stamp + ": " + lb_path + lockbox_file_name + " copied to " + archive_path)
            true 
        with ex -> 
            fH.WriteLine(generate_time_stamp + ": " + "An error occrred trying to move or copy " + 
                         lb_path + lockbox_file_name + " to " + archive_path)
            printfn "%A" ex
            false
    rc

2 个答案:

答案 0 :(得分:3)

匹配表达式的所有分支必须具有相同的类型。根据您发布的错误消息判断,匹配表达式的第一个分支的类型为string -> bool,这意味着您对FileMaint.fm.archive_lb_file的调用可能缺少一个参数:它需要另一个string,并且在获得一个之后,它承诺返回bool

由此,解决方案将包含两部分:

  1. 将缺失的参数传递给FileMaint.fm.archive_lb_file(我不能再帮助你了,因为我没有看到该功能的定义,因此不知道是什么缺少参数应该是)。
  2. 使test_print函数返回相同的类型 - 即bool。要实现这一点,只需添加一个返回值:
  3.  let test_print fn = 
        printfn "%A" fn
        true
    

    那就是说,我怀疑你的程序实际上有一个逻辑错误:FileMaint.fm.archive_lb_file返回一个bool,但是你忽略了它。你应该?如果返回值对您不重要,该函数应该首先将其返回吗?

答案 1 :(得分:3)

匹配语句中的所有模式必须返回相同的类型。您的test_print会返回单位,但您的FileMaint.fm.archive_lb_file会返回一个函数string -> bool。如果您将方法更改为

let test_print fn =
    printfn "%A" fn
    true

将修复你得到的错误,即使这看起来很奇怪。

编辑: 由于您发布了缺失的函数,因此您看到的错误是由于未在调用中传递copy_only参数引起的。

    match fn with
    | "cb_lockbox.txt" -> FileMaint.fm.archive_lb_file lb_dir archive_dir fn true
    | "ics_lockbox.txt" -> (test_print fn) 
    | "ic_lockbox.txt" -> test_print fn
    | _ -> test_print "does not exist"

添加true将调用该函数。你没有收到电话错误的原因是由于功能的干扰。

https://fsharpforfunandprofit.com/posts/currying/