创建一个生成多个ocaml列表的函数

时间:2017-02-08 07:32:04

标签: ocaml

我有一个功能:

let rec multiply x ls =
match ls with 
[] -> []
| h::tl -> (x * h) :: multiply x tl 

乘以2 [1; 2; 3] = [2; 4; 6]

我想要一个从n乘以0到0的函数。由于基本情况我一直遇到问题:

let rec multiply_all x ls = if x > 0 
then (multiply n ls) :: multiply_all (n-1) (ls) else ????

我不确定在别人之后放什么。我试着做到了

if x > 1 then (multiply n ls) :: multiply_all (n-1) (ls) else multiply all 1. 

但这不起作用。

3 个答案:

答案 0 :(得分:1)

由于1必须返回列表,因此放置multiply_all肯定不起作用。所以你需要一个列表(int列表)放在那里。但它应该是哪个列表?

简短的回答是,在这种简单的情况下,您需要的列表通常是空列表:[]

作为稍微长一点的答案,我们可以考虑与multiply_all 0multiply_all 1等的预期结果相关的multiply_all 2的情况,并尝试找到适合的模式。我们希望multiply_all的行为如下:

# multiply_all 2 [1;2;3];;
- : int list list = [[2; 4; 6]; [1; 2; 3]]
# multiply_all 1 [1;2;3];;
- : int list list = [[1; 2; 3]]

因此,使用一些数字 N 作为第一个参数调用multiply_all应该会给我们一个长度为 N 的列表。特别是, N = 0的multiply_all应该给出一个长度为0的列表。长度为0的列表是空列表。

以下是您完成的定义:

let rec multiply_all x ls =
  if x > 0 then (multiply x ls) :: multiply_all (x-1) (ls) else []

答案 1 :(得分:0)

只是另一个解决方案:

let multiply_all n l =
  let multiply n= List.map (( * ) n) in
  let rec aux i acc =
    if i > n then acc
    else aux (i+1) (multiply i l :: acc)
  in
  aux 1 [] 
;;

测试:

# multiply_all 5 [1;2;3];;
- : int list list =
[[5; 10; 15]; [4; 8; 12]; [3; 6; 9]; [2; 4; 6]; [1; 2; 3]]

答案 2 :(得分:-1)

首先,您的multiply方法非常低效,因为它不是尾递归。此外,标准库为您提供了使这类函数更易于编写的工具:

let multiply n = List.map (( * ) n);;;
val multiply : int -> int list -> int list = <fun>

multiply 5 [1;2;3];;
- : int list = [5; 10; 15]

注意:另外,如果不对代码进行模糊处理,请使用部分应用程序。

截至multiply_all,如果没有JaneStreet Core,我不确定如何实现它(请参阅this question)。但是,这是使用Core

的可能实现
open Core.Std;; (*Using Core*)
let multiply_all n l =
  let multiples = List.init n ~f:(fun x -> n-x) in (*This doesn't exist in Pervasives*)
  List.map multiples ~f:(fun m -> multiply l m);;
val multiply_all : int list -> int -> int list list = <fun>

multiply_all 5 [1;2;3];;
- : int list list = [[5; 10; 15]; [4; 8; 12]; [3; 6; 9]; [2; 4; 6]; [1; 2; 3]]

希望它有所帮助。我会根据我对List.init的调查结果更新此答案。