Это
let rec ldzialanie listA listB operator = function
| LCons(xA, xfA), LCons(xB, xfB), '+' ->
говорит о том, что при оценке ldzialanie x y z
получается функция , которая принимает в качестве аргумента тройку.
Это не то, что вы хотите - вы хотите, чтобы ldzialanie x y z
создайте 'a lazyList
.
Вы хотите сопоставить вместо аргументов.
Вам также нужно принудительно задавать хвосты ваших ленивых списков при рекурсии - рекурсия требует 'a lazyList
, а не unit -> 'a lazyList
.
В качестве третьего пункта, function () -> xf()
эквивалентен xf
.
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, LNil, _ -> LNil
| LNil, LCons(x, xf), _ -> LCons(x, xf)
| LCons(x, xf), LNil, _ -> LCons(x, xf)
| LCons(_), LCons(_), _ -> failwith "Not existible operator"
;;
Давайте немного укоротим это.
Если вы посмотрите на «ноль случаев», то результат, когда один аргумент равен 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);;