我是OCaml的新手,我正在尝试编写一个函数来执行此操作:
(4,a)(1,b)(2,c)(2,a)(1,d)(4,e) --> ((4 a) b (2 c) (2 a) d (4 e))
这就是我写的:
let rec transform l =
match l with
| (x,y)::t -> if x = 1 then y::transform(t) else [x; y]::transform(t)
| [] -> []
我把它放在ocaml解释器中但是生成的错误如下:
Error: This expression has type int list
but an expression was expected of type int
有人能帮忙吗?
答案 0 :(得分:2)
您的示例转换并未明确该值的类型应该是什么。
如果它们应该是列表,则结果不是OCaml中的可能列表。 OCaml列表是同类的,即列表的所有元素具有相同的类型。这(实质上)是编译器抱怨的内容。
<强>更新强>
查看代码,问题在于:
if x = 1
then y :: transform (t)
else [x; y] :: transform t
让我们说y的类型是'a
。 then
之后的表达式似乎具有类型'a list
,因为y是列表的头部。 else
之后的表达式似乎具有类型'a list list
,因为包含y的列表是列表的头部。它们的类型不同。
答案 1 :(得分:2)
主要问题是决定如何将某些内容表示为(4 a)
或b
。通常的OCaml表示某种东西或其他东西的方式是变体,所以让我们定义其中一种:
type 'a element =
| Single of 'a
| Count of int * 'a
let rec transform = function
| [] -> []
| (x,y)::t ->
if x = 1 then Single y::transform t
else Count (x, y)::transform t
请注意,除非您使用顶层注册打印机,否则不会以您想要的方式打印。
或更好:
let compact (x, y) =
if x = 1 then Single y else Count (x, y)
let transform list = List.map compact list