我是Ocaml的新手,我正在编写代码来替换嵌套的Ocaml列表中的元素。我的代码如下:
type 'a sexp = S of 'a | L of 'a sexp list
我的替换函数(它替换了嵌套列表中所有出现的元素a和b)如下:
let rec subst a b list = match list with
| [] -> list
| S s :: t -> if s = a then (S b) :: (subst a b t) else (S s) :: (subst a b t)
| L l :: t -> (subst a b l) :: (subst a b t)
尽管多次尝试(近6个小时),但我还是无法编译此代码..请帮忙!
答案 0 :(得分:3)
我可以建议先写一个subst
类型的函数'a -> 'a -> 'a sexp -> 'a sexp
吗?它会读
let subst x y sexp =
let rec visit = function
| S z -> S (if z = x then y else z)
| L sexps -> L (List.map visit sexps)
in
visit sexp
并且很好地和惯用地捕获了在sexp
上递归的想法。
现在,要获得一个对列表而不是单个sexp
进行操作的函数,您可以轻松定义subst_list
类型的函数'a -> 'a -> 'a sexp list -> 'a sexp list
:
let subst_list x y sexps = List.map (subst x y) sexps
更好的是从抽象中抽象出来,并使用类型为map
的更普遍适用的函数('a -> 'b) -> 'a sexp -> 'b sexp
来执行sexp
s的结构保留映射:
let map f sexp =
let rec visit = function
| S x -> S (f x)
| L sexps -> L (List.map visit sexps)
in
visit sexp
然后按照subst
和map
的方式定义subst_list
,与subst
一样:
let subst x y sexp = map (fun z -> if z = x then y else z) sexp
let subst_list x y sexps = List.map (subst x y) sexps
答案 1 :(得分:2)
注意:在这里使用F#编译器;我这台计算机上没有OCaml编译器。
subst
函数的最后一行有错误:它应该如下:
| L l :: t -> L (subst a b l) :: (subst a b t)
所以完整的代码看起来像这样:
type 'a Sexp =
| S of 'a
| L of 'a Sexp list
let rec subst (a) (b) (lst : 'a Sexp list) =
match lst with
| [] -> lst
| S s :: t -> if s = a then (S b) :: (subst a b t) else (S s) :: (subst a b t)
| L l :: t -> L (subst a b l) :: (subst a b t)
let test () =
let (lst : int Sexp list) = [S 1; L [S 2; L [S 3]; S 4]; S 5]
let a = 2
let b = 3
subst a b lst
test()
的输出是
[S 1; L [S 3; L [S 3]; S 4]; S 5]
原因是您的函数subst
返回'a Sexp list
。如果您忽略了最后一行的L
构造函数,那么subst a b l
的类型为'a Sexp list
,您试图将其与另一个类型为'a Sexp list
的列表合并。这不起作用。
这也不是您的意图,因为您希望最终得到'a Sexp list
类型的实体,这意味着您必须使用类型为'a Sexp
的列表来构建'a Sexp list
类型的元素。通过指定L
构造函数,您将创建一个'a Sexp list
类型的元素,现在可以将其与列表的其余部分一起使用。
答案 2 :(得分:1)
看起来你的函数subst
应该返回'a sexp list
类型的东西。这就是第一和第二场比赛的回归。
在第三个匹配的情况下,您的返回值为:
(subst a b l) :: (subst a b t)
由于您的函数返回'a sexp list
,因此这种类型没有多大意义。列表的头部是'a sexp list
类型,列表的尾部是类型'a sexp list
的。提出具有这种结构的任何列表是非常困难的。我想你想要的是列表的头部是'a sexp
类型。
如果您希望列表的头部属于'a sexp
类型,则需要某种方法将一系列内容打包成一个单独的a sexp
。如果这还不够,请查看您的L
构造函数。这正是它的作用。