在 sml 中对两个列表求和

Sum two list in sml

sml 中有两个列表,我想将一个添加到另一个

val one = [1.1,2.2,3.3] : real list;
val two = [4.4,5.5,6.6] : real list;

结果应该是 [5.5, 7.7, 9.9]。

我不确定我这样做对不对,但基本上我是想将这两个列表传递给一个有趣的人,然后做一些事情,比如 one[0] + two[0]

有没有更好的方法呢?谢谢~

SML 列表通常不按索引访问。列表可以是 empty 或一个值和一个列表。通过这个递归定义,我们可以得到任意长度的列表。这也意味着我们只需要对两种情况进行操作来迭代一个列表:空列表,或者一个包含一个元素的列表和另一个列表。

考虑一个 map 函数,它将一个函数 f 映射到一个列表和 returns 另一个列表。

fun map f []      = []
  | map f (x::xs) = f x :: map f xs

我们可以为 int list 中的每个元素加 1,例如:

map (fn x => x + 1) [2, 3, 4]

这会产生 [3, 4, 5]

映射两个列表非常简单。

fun map2 f [] []           = [] 
  | map2 f (x::xs) (y::ys) = (* ... *)

虽然这不适应不同长度的列表或如何处理它们。

如果你能弄清楚这一点,完成分配给你的任务就是 map2 的一个非常简单的应用。

关注一下怎么样...

fun add_lists any [] = any
  | add_lists [] any = any
  | add_lists (a::bs) (c::ds): real list = (a + c) :: add_lists bs ds;

测试

> val add_lists = fn: real list -> real list -> real list
> add_lists [] [];
> val it = []: real list;
> add_lists [1.0] [];
> val it = [1.0]: real list;
> add_lists [] [2.1];
> val it = [2.1]: real list;
> add_lists [1.3] [2.0];
> val it = [3.3]: real list;
> add_lists [1.1, 2.2] [3.2, 4.5];
> val it = [4.300000000000001, 6.7]: real list;
> add_lists [1.3] [2.7, 3.5];
> val it = [4.0, 3.5]: real list;
> add_lists [] [2.3, 3.2];
> val it = [2.3, 3.2]: real list;
> add_lists [1.2, 2.1] [];
> val it = [1.2, 2.1]: real list;
> add_lists [1.0, 2.0, 3.0] [4.0, 5.0, 6.0];
> val it = [5.0, 7.0, 9.0]: real list;
> add_lists [1.1,2.2,3.3] [4.4,5.5,6.6];
> val it = [5.5, 7.7, 9.899999999999999]: real list;

插图

let initialState = Interpreter.getFirstState();
let interpretationResult = Interpreter.interpret('', initialState);

function eval_code(code) {
  let input_provider = document.querySelector('#interpreter-input-provider');
  let code_to_execute = (code || input_provider.value || '').trim() + ';';

  if (code_to_execute) {
    try {
      interpretationResult = Interpreter.interpret(code_to_execute, interpretationResult.state);
      console.log(interpretationResult.state.toString());

      if (interpretationResult.warnings && interpretationResult.warnings.length) {
        interpretationResult.warnings.forEach(warning => console.log('[Evaluation Warning]\n', warning.toString()));
      }
    } catch (error) {
      console.error('[Evaluation Error]\n', error.message);
    }

    input_provider.value = '';
  }
}

function eval_definition() {
  const fun_definition = `fun add_lists any [] = any
  | add_lists [] any = any
  | add_lists (a::bs) (c::ds): real list = (a + c) :: add_lists bs ds;`;
  eval_code(fun_definition);
}

function run_tests() {
  const input_array = [
    "add_lists [] [];",
    "add_lists [1.0] [];",
    "add_lists [] [2.1];",
    "add_lists [1.3] [2.0];",
    "add_lists [1.1, 2.2] [3.2, 4.5];",
    "add_lists [1.3] [2.7, 3.5];",
    "add_lists [] [2.3, 3.2];",
    "add_lists [1.2, 2.1] [];",
    "add_lists [1.0, 2.0, 3.0] [4.0, 5.0, 6.0];",
    "add_lists [1.1,2.2,3.3] [4.4,5.5,6.6];"
  ];

  input_array.forEach(input => eval_code(input));
}
eval_definition();
run_tests();

// interpretationResult = Interpreter.interpret('fun f y = x | f 10 = "???";', interpretationResult.state);
// console.log(interpretationResult.warnings);
#interpreter-input-provider {
  display: block;
  // min-width: 200px;
  //min-height: 30%;
  width: 90%
}

button {
  width: 20%;
  height: 3em;
  cursor: pointer;
}
<script src="https://unpkg.com/@sosml/interpreter@^1.5.0/build/interpreter.min.js"></script>

<section id="interpretation-input">
  <button id="eval-top" onclick="eval_code();">Eval</button>
  <textarea id="interpreter-input-provider" rows="20">

  </textarea>
  <button id="eval-bottom" onclick="eval_code();">Eval</button>

</section>
<section id="interpretation-output">

</section>

<code id="fun-definition" hidden>
fun add_lists any [] = any
  | add_lists [] any = any
  | add_lists (a::bs) (c::ds): real list = (a + c) :: add_lists bs ds;
</code>