【问题标题】:This expression has type 'a list option but an expression was expected of type 'b list此表达式具有类型 'a 列表选项,但预期的表达式类型为 'b 列表
【发布时间】:2022-07-06 01:40:00
【问题描述】:

我正在 OCaml 中编写一个函数,它使用 type 选项和 List.fold_right 返回列表中最长的列表。

let longest (lst : 'a list list) : 'a list option = 
  List.fold_right (fun (i : 'a list)  (y : 'a list option) -> if List.length i > List.length y then (Some i) y else y) lst None 

但是我不断收到以下错误。

This expression has type 'a list option
but an expression was expected of type 'b list

该函数应返回Some,后跟最长列表,如果为空,则返回None

【问题讨论】:

  • 模式首先匹配列表。如果为空,则返回 None,如果 x::xs 返回 Some ...,则使用 x 作为折叠的初始元素。无需每次都在折叠内构造和匹配选项,避免您的类型错误。
  • let longest( lst : 'a list list) (x : 'a list option) = match lst with | [] -> None | x :: xs -> Some ( List.fold_right (fun i y -> if List.length i > List.length y then i else y) x xs) `此表达式的类型为'a list list list,但表达式应为'a list 类型。类型变量'b 出现在'b list list 中`但是,当我收到此错误时我试图模式匹配
  • 你混淆了 List.fold_right 的参数,x xs 应该是 xs x
  • 什么是最长的未使用的x 参数?
  • 哦,那是我的错,该函数应该返回“列表选项”。谢谢指出

标签: list ocaml


【解决方案1】:

让我们让它更容易理解。

let longest (lst : 'a list list) (x : 'a list option) = 
  List.fold_right 
    (fun (i : 'a list)  (y : 'a list option) -> 
       if List.length i > List.length y then (Some i) y 
       else y) 
    lst 
    None 

此投诉的具体问题与:

List.length y

在这种情况下,y 应该是 'a list option 类型,但 List.length 需要 'a list 类型的值。

您需要在传递给List.fold_right 的函数中进行一些模式匹配,以确定初始化值(在您的代码中容易混淆地表示为y)是None 还是Some ...,然后进行相应处理.

它可能如下所示。请注意,您使用的类型注释是无关的,因为 OCaml 会推断类型。

let longest lst =
  List.(
    let f x i =
      match i with 
      | None                                  -> ...
      | Some lst' when length x > length lst' -> ...
      | _                                     -> ...
    in
    fold_right f lst None
  )

【讨论】:

    【解决方案2】:

    将 [] 作为特殊情况处理,删除未使用的 x 参数并减少每个列表调用 List.length 的次数我得到这个:

    let longest lst =
      match lst with   
       | [] -> None   
       | x :: xs -> 
          Some (fst (List.fold_right
            (fun i ((y, ly) as p) ->
              let li = List.length i
              in
                if li > ly
                then (i, li)
                else p)
            xs
            (x, List.length x)));;
    
    val longest : 'a list list -> 'a list option = <fun>
    # longest [];;
    - : 'a list option = None
    # longest [[1]; [1;2;3]; [1;2]];;
    - : int list option = Some [1; 2; 3]
    

    【讨论】:

    • 感谢 Goswin 帮助我
    • 没问题,除了优化之外,您已经完成了所有工作。
    • 我不知道你为什么要这样处理[]List.fold_right 已经有一个完全有效的方法来处理一个空列表而无需编写额外的代码:它返回初始值。
    • 您不希望累加器成为选项类型,否则您必须在每个循环中匹配它。
    猜你喜欢
    • 2018-03-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-04-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多