module ChurchFold open System let nil (c:'a->'b->'b) (n:'b) : 'b = n let cons (x:'a) (xs:('a->'b->'b)->'b->'b) : ('a->'b->'b)->'b->'b = fun c n -> c x (xs c n) let toList (xs:('a->'b->'b)->'b->'b) : 'a list = xs (fun x acc -> x :: acc) [] let ofList (ls:'a list) : (('a->'b->'b)->'b->'b) = List.foldBack (fun x acc -> cons x acc) ls nil let foldWithPredicate (churchList:(int->int list->int list)->int list->int list) (f:int->int->int) (p:int->bool) (acc:int) : int = let regularList = toList churchList let rec foldTailRec lst accumulator = match lst with | [] -> accumulator | head :: tail -> if p head then foldTailRec tail (f accumulator head) else foldTailRec tail accumulator foldTailRec regularList acc [] let main _ = let numbers = ofList [1; 2; 3; 4; 5] let add x y = x + y let isEven x = x % 2 = 0 let greaterThan2 x = x > 2 printfn "Исходный список: [1; 2; 3; 4; 5]" printfn "" let sumEven = foldWithPredicate numbers add isEven 0 printfn "Сумма четных чисел (предикат isEven): %d" sumEven let sumGreater2 = foldWithPredicate numbers add greaterThan2 0 printfn "Сумма чисел больше 2 (предикат > 2): %d" sumGreater2 let multiply x y = x * y let productEven = foldWithPredicate numbers multiply isEven 1 printfn "Произведение четных чисел: %d" productEven printfn "" printfn "Демонстрация работы с различными предикатами:" let isOdd x = x % 2 = 1 let sumOdd = foldWithPredicate numbers add isOdd 0 printfn "Сумма нечетных чисел: %d" sumOdd let isPositive x = x > 0 let countPositive = foldWithPredicate numbers (fun acc _ -> acc + 1) isPositive 0 printfn "Количество положительных чисел: %d" countPositive 0