ocaml函数要求我返回单位,而不是';单子

ocaml函数要求我返回单位,而不是';单子,ocaml,Ocaml,我最近开始用ocaml编写代码,在定义我希望函数返回的内容时,这种编程语言非常明智。 我想写一个函数,它使用两个列表作为参数(应该是升序的,元素类型为int),并返回一个包含前两个列表的所有元素的列表,也是升序的 以下是我迄今为止所取得的成就: let inter l1 l2 = let rec aux l1 l2 l3= if List.hd l1<List.hd l2 then aux (List.tl l1) l2 (List.hd l1 :: l3) else (if List.h

我最近开始用ocaml编写代码,在定义我希望函数返回的内容时,这种编程语言非常明智。 我想写一个函数,它使用两个列表作为参数(应该是升序的,元素类型为int),并返回一个包含前两个列表的所有元素的列表,也是升序的

以下是我迄今为止所取得的成就:

let inter l1 l2 =
let rec aux l1 l2 l3=
if List.hd l1<List.hd l2 then aux (List.tl l1) l2 (List.hd l1 :: l3)
else (if List.hd l1>List.hd l2 then aux l1 (List.tl l2) (List.hd l2::l3)
      else (if l1 = [] then List.fold_left (fun x y -> y::x) l3 l2
            else if l2=[] then List.fold_left (fun x y -> y::x) l3 l1
     ))
  in List.rev (aux l1 l2 []);;
当我调用该函数时,它工作得很好,但它的工作方式与预期的一样,但困扰我的是错误消息。知道为什么会出现吗


PS:我使用Emacs-Tuareg模式作为文本编辑器和编译器。

Th
if/else
语法结构是一个表达式。整个表达式的类型由分支返回的表达式类型定义。显然,它们必须是同一类型的。如果没有指定
else
分支,则假定省略的else分支是一个unit类型的表达式,基本上
If c then e
If c then e else()的缩写

表达方式:

 if l2=[] then List.fold_left (fun x y -> y::x) l3 l1
实际上是以下内容的简写:

 if l2=[] then List.fold_left (fun x y -> y::x) l3 l1 else ()
因此,OCaml试图将
List.fold_left(fun x y->y::x)l3 l1
()
统一起来。它们肯定有不同的类型。如果添加显式的
else
分支,则所有内容都将进行类型检查(不确定正确性):

让内部l1和l2=
让rec辅助l1 l2 l3=
如果是List.hd l1List.hd l2,则为辅助l1(List.tl l2)(List.hd l2::l3)
else(如果l1=[]则List.fold_left(有趣的x y->y::x)l3 l2
else如果l2=[]则List.fold_left(有趣的x y->y::x)l3 l1 else[]
))
在List.rev(辅助l1 l2[]);中;;
你的挫折感可能是因为对类似C的编程语言很熟悉。当试图在其中强制使用C编程风格时,OCaml可能会令人沮丧。模式匹配是OCaml非常强大的功能,可以简化您的解决方案:

let rec inter l1 l2 =
  match l1, l2 with
  | [], _ -> l2
  | _, [] -> l1
  | (h1 :: t1), (h2 :: t2) ->
    if h1 <= h2 then
      h1 :: inter t1 l2
    else
      h2 :: inter l1 t2
let rec inter l1 l2=
将l1、l2与
|[],[uuu2->l2
|_u,[]->l1
|(h1::t1)、(h2::t2)->

if h1Th
if/else
句法结构是一个表达式。整个表达式的类型由分支返回的表达式类型定义。显然,它们必须是同一类型的。如果没有指定
else
分支,则假定省略的else分支是一个unit类型的表达式,基本上
If c then e
If c then e else()的缩写

表达方式:

 if l2=[] then List.fold_left (fun x y -> y::x) l3 l1
实际上是以下内容的简写:

 if l2=[] then List.fold_left (fun x y -> y::x) l3 l1 else ()
因此,OCaml试图将
List.fold_left(fun x y->y::x)l3 l1
()
统一起来。它们肯定有不同的类型。如果添加显式的
else
分支,则所有内容都将进行类型检查(不确定正确性):

让内部l1和l2=
让rec辅助l1 l2 l3=
如果是List.hd l1List.hd l2,则为辅助l1(List.tl l2)(List.hd l2::l3)
else(如果l1=[]则List.fold_left(有趣的x y->y::x)l3 l2
else如果l2=[]则List.fold_left(有趣的x y->y::x)l3 l1 else[]
))
在List.rev(辅助l1 l2[]);中;;
你的挫折感可能是因为对类似C的编程语言很熟悉。当试图在其中强制使用C编程风格时,OCaml可能会令人沮丧。模式匹配是OCaml非常强大的功能,可以简化您的解决方案:

let rec inter l1 l2 =
  match l1, l2 with
  | [], _ -> l2
  | _, [] -> l1
  | (h1 :: t1), (h2 :: t2) ->
    if h1 <= h2 then
      h1 :: inter t1 l2
    else
      h2 :: inter l1 t2
let rec inter l1 l2=
将l1、l2与
|[],[uuu2->l2
|_u,[]->l1
|(h1::t1)、(h2::t2)->

如果h1同意w.r.t的风格问题:我建议初学者远离
List.hd
。一旦你习惯了使用模式,就可以重新审视这条规则,偶尔使用
List.hd
,当然这是更好的选择。谢谢你的解释。我知道模式匹配,但我发现用c风格编程在逻辑上更容易编写代码。我会试着习惯它,因为它比我目前的编程风格要少编写代码。同意w.r.t风格问题:我建议初学者远离
List.hd
。一旦你习惯了使用模式,就可以重新审视这条规则,偶尔使用
List.hd
,当然这是更好的选择。谢谢你的解释。我知道模式匹配,但我发现用c风格编程在逻辑上更容易编写代码。我会尽量习惯它,因为它比我目前的编程风格要少编写代码。