Function 如何使函数在惰性列表(也称为“流”)上运行?

Function 如何使函数在惰性列表(也称为“流”)上运行?,function,functional-programming,ocaml,Function,Functional Programming,Ocaml,我必须生成一个函数,它接受两个惰性列表和操作符,比如+,-,*,/并在操作后返回一个惰性列表。例如,[1;2;3],[2;3;4;5]+,将返回[3;5;7;5]。懒散列表像常规列表一样引入,因为它更具可读性 我知道它是如何实现的,但在函数->之后出现了一个错误。它说这个表达式有类型 int lazyList*int lazyList*char->int lazyList 但表达式应为int-lazyList类型 type 'a lazyList = LNil | LCons of 'a * (

我必须生成一个函数,它接受两个惰性列表和操作符,比如+,-,*,/并在操作后返回一个惰性列表。例如,[1;2;3],[2;3;4;5]+,将返回[3;5;7;5]。懒散列表像常规列表一样引入,因为它更具可读性

我知道它是如何实现的,但在函数->之后出现了一个错误。它说这个表达式有类型 int lazyList*int lazyList*char->int lazyList 但表达式应为int-lazyList类型

type 'a lazyList = LNil | LCons of 'a * (unit -> 'a lazyList);;

let rec ldzialanie listA listB operator = function
| LCons(xA, xfA), LCons(xB, xfB), '+' -> LCons(xA + xB, function() -> ldzialanie xfA xfB '+')
| LCons(xA, xfA), LCons(xB, xfB), '-' -> LCons(xA - xB, function() -> ldzialanie xfA xfB '-')
| LCons(xA, xfA), LCons(xB, xfB), '/' -> LCons(xA / xB, function() -> ldzialanie xfA xfB '/')
| LCons(xA, xfA), LCons(xB, xfB), '*' -> LCons(xA * xB, function() -> ldzialanie xfA xfB '*')
| LNil, LNil, _ -> LNil
| LNil, LCons(x, xf), _ -> LCons(x, function() -> xf())
| LCons(x, xf), LNil, _ -> LCons(x, function() -> xf())
| LCons(_), LCons(_), _ -> failwith "Not existible operator"
;;

首先,这里有些混乱

let rec ldzialanie listA listB operator = function
    | LCons(xA, xfA), LCons(xB, xfB)
您是说应用于参数listA、listB和operator的ldzialanie返回一个函数。返回的函数取三元组,模式匹配

相反,您应该对ldzialanie的参数使用match-to-pattern匹配

或者,如果您希望使用函数定义ldzialanie,则必须记住该函数是ldzialanie而不是ldzialanie listA listB运算符

还要注意,两个版本都有不同的类型,因为后者以三元组作为参数

ldzialanie  : int lazyList -> int lazyList -> char -> int lazyList 
ldzialanie2 : int lazyList * int lazyList * char -> int lazyList 
在进行递归调用时,需要记住这一点

关于如何计算结果,您应该知道 LConsxA,xfA xfA的类型不是“懒散列表”,而是“单位->”懒散列表。因此,在需要一个“懒散列表”的情况下,不能将xfA作为参数传递。

type 'a lazyList = LNil | LCons of 'a * (unit -> 'a lazyList);;

let rec ldzialanie listA listB operator = function
| LCons(xA, xfA), LCons(xB, xfB), '+' -> LCons(xA + xB, function() -> ldzialanie xfA xfB '+')
| LCons(xA, xfA), LCons(xB, xfB), '-' -> LCons(xA - xB, function() -> ldzialanie xfA xfB '-')
| LCons(xA, xfA), LCons(xB, xfB), '/' -> LCons(xA / xB, function() -> ldzialanie xfA xfB '/')
| LCons(xA, xfA), LCons(xB, xfB), '*' -> LCons(xA * xB, function() -> ldzialanie xfA xfB '*')
| LNil, LNil, _ -> LNil
| LNil, LCons(x, xf), _ -> LCons(x, function() -> xf())
| LCons(x, xf), LNil, _ -> LCons(x, function() -> xf())
| LCons(_), LCons(_), _ -> failwith "Not existible operator"
;;
let rec ldzialanie listA listB operator = function
| LCons(xA, xfA), LCons(xB, xfB), '+' ->
表示计算ldzialanie x y z生成一个以三元组为参数的函数。 这不是你想要的——你想让ldzialanie x y z制作一个“懒汉名单”

type 'a lazyList = LNil | LCons of 'a * (unit -> 'a lazyList);;

let rec ldzialanie listA listB operator = function
| LCons(xA, xfA), LCons(xB, xfB), '+' -> LCons(xA + xB, function() -> ldzialanie xfA xfB '+')
| LCons(xA, xfA), LCons(xB, xfB), '-' -> LCons(xA - xB, function() -> ldzialanie xfA xfB '-')
| LCons(xA, xfA), LCons(xB, xfB), '/' -> LCons(xA / xB, function() -> ldzialanie xfA xfB '/')
| LCons(xA, xfA), LCons(xB, xfB), '*' -> LCons(xA * xB, function() -> ldzialanie xfA xfB '*')
| LNil, LNil, _ -> LNil
| LNil, LCons(x, xf), _ -> LCons(x, function() -> xf())
| LCons(x, xf), LNil, _ -> LCons(x, function() -> xf())
| LCons(_), LCons(_), _ -> failwith "Not existible operator"
;;
您希望在参数上进行匹配。 在递归时,您还需要强制执行惰性列表的尾部-递归需要一个“懒散列表,而不是单元->”懒散列表。 作为第三点,function->xf等同于xf

让我们把这个缩短一点

如果查看nil情况,当一个参数为LNil时,结果是另一个参数

let rec ldzialanie listA listB operator = match listA, listB, operator with
    LCons(xA, xfA), LCons(xB, xfB), '+' -> LCons(xA + xB, function() -> ldzialanie (xfA()) (xfB()) '+')
  | LCons(xA, xfA), LCons(xB, xfB), '-' -> LCons(xA - xB, function() -> ldzialanie (xfA()) (xfB()) '-')
  | LCons(xA, xfA), LCons(xB, xfB), '/' -> LCons(xA / xB, function() -> ldzialanie (xfA()) (xfB()) '/')
  | LCons(xA, xfA), LCons(xB, xfB), '*' -> LCons(xA * xB, function() -> ldzialanie (xfA()) (xfB()) '*')
  | LNil, r, _ -> r
  | l, LNil, _ -> l
  | LCons(_), LCons(_), _ -> failwith "Not existible operator"
;;
在非nil的情况下仍然有很多重复,并且递归是否正确并不完全明显。 如果首先将运算符字符转换为函数,则可以将它们压缩为一个大小写

我还将首先使用运算符参数,以便您可以定义例如let add_lists=ldzialanie+

大概是这样的:

let to_function x = match x with
    '+' -> ( + )
  | '*' -> ( * )
  | '/' -> ( / )
  | '-' -> ( - )
  | _ -> failwith "Non-existent operator";;

let rec ldzialanie_helper op listA listB = match listA, listB with
    LCons(xA, xfA), LCons(xB, xfB) -> LCons(op xA xB, function() -> ldzialanie_helper op (xfA()) (xfB()))
  | LNil, r  -> r
  | l, LNil  -> l;;

let ldzialanie op = ldzialanie_helper (to_function op);;
let to_function x = match x with
    '+' -> ( + )
  | '*' -> ( * )
  | '/' -> ( / )
  | '-' -> ( - )
  | _ -> failwith "Non-existent operator";;

let rec ldzialanie_helper op listA listB = match listA, listB with
    LCons(xA, xfA), LCons(xB, xfB) -> LCons(op xA xB, function() -> ldzialanie_helper op (xfA()) (xfB()))
  | LNil, r  -> r
  | l, LNil  -> l;;

let ldzialanie op = ldzialanie_helper (to_function op);;