如何将 OCaml 列表拆分为头部和尾部?

How do I split an OCaml list into head and tail?

我正在学习 OCaml,现在,当我需要访问头部时,我使用 match l with h::t -> 来拆分列表。但我敢肯定 has 是以这种方式拆分列表的更好方法。我似乎无法在网上找到很多。可能我没看对方向

这是最好的方法。

有函数List.hdList.tl可以得到hdtl但是标准库中没有函数可以得到头尾合二为一移动。此外 List.hdList.tl 是不安全的:如果你给它们一个空列表,它们会引发运行时异常:

# List.hd [];;
Exception: Failure "hd".

如果您 100% 确定参数不能为空,则可以安全地使用它们,但您的推测在实践中往往不正确。 List.hdtl 可能是非常好的错误来源。

使用 let 的模式:let (h::t) = l in ... 是可能的,但它也有运行时失败的风险,但编译器会告诉你你的模式并不详尽并且缺乏 let (h::t) = l in ... 的处理=21=].

match 可以有多个案例,您可以覆盖 [] 的案例:match l with [] -> ... | (h::t) -> ...。如果您忘记 [] 的大小写,编译器会警告您。

我不懂 OCaml,但 Haskell 提供了这些,您可能可以轻松翻译:

-- I think ML might write this signature
-- uncons : 'a list -> ('a * 'a list) option
uncons :: [a] -> Maybe (a, [a])
uncons (x : xs) = Just (x, xs)
uncons [] = Nothing

maybe :: b -> (a -> b) -> Maybe a -> b
maybe def f Nothing = def
maybe def f (Just x) = f x

然后你可以这样写

drop1 :: [a] -> [a]
drop1 = maybe [] snd . uncons

这个问题的 OCaml 方法是表达式

match l with
| [] -> some_expr
| x :: xs -> some_other_expr
  • 最糟糕的解决方案是使用 List.hdList.hd,可能导致运行时异常。

  • 第二个更糟糕的解决方案是不完全匹配,例如 match l with x :: xs 也会导致相同的运行时错误,但您至少会收到编译时警告,以及匹配的情况你错过了。

注意,部分不使用的匹配可以忽略, 所以你的代码是自我记录的:

let hd_option lst =
match lst with
| [] -> None
| x :: _ -> Some x (* the tail is not used, so I just don't name it *)