2014-02-08 5 views
0

Я использую OCaml для записи функции, которая принимает список int и int-элемента и возвращает список пар, где первый элемент каждой пары является элементом int и второй элемент пары является членом из списка. Например, допустим, у меня есть номер 1 и список [10; 20; 30] в качестве входных данных. Мне нравится функция для возврата [(1, 10); (1, 20); (1, 30)]. Я написал следующую функцию:сопряжение int со списком int в OCaml

let rec f (lst : int list) (elm : int) : (int*int) list = 
    match lst with 
    | [] -> failwith "empty list" 
    | [x] -> [(x, elm)];; 

Я получаю следующее сообщение об ошибке:

Characters 59-120:                
Warning 8: this pattern-matching is not exhaustive.        
Here is an example of a value that is not matched:        
_::_::_ val f : int list -> int -> (int * int) list = <fun> 

Что мне не хватает?

ответ

1

Вот ваш код

let rec f (lst : int list) (elm : int) : (int*int) list = 
    match lst with 
    | [] -> failwith "empty list" 
    | [x] -> [(x, elm)] 

В вашем match, вы перечислили два случая: [] и [x].

Ваш первый случай: [], вы имеете в виду empty, без проблем.

Ваш второй случай: [x], что вы хотите иметь в виду? В OCaml это означает a list with only one element.

Как насчет случаев, когда имеется более одного элемента?

Для любых if else или match with вы должны включить все случаи.

Когда вы исправите эту проблему, вы скоро обнаружите, что вы действительно пропустили что-то еще.


Вот правильный код:

let rec f e l = 
    match l with 
    | [] -> [] 
    | x::[] -> [(e,x)] 
    | x::tl -> (e,x)::(f e tl) 

Примечание

  1. выше код не tail-recursive и вы обычно должны рассмотреть об этом, я оставлю это для вас.
  2. вам не нужно ;;, если вы пишете код в файл и скомпилировать файл
  3. Вам не нужно объявлять типы в большинстве случаев, и это одна из лучших, что OCaml имеет.
+0

Спасибо, как я могу получить элементы в списке, который имеет более чем один элемент? Я знаю, что есть что-то вроде h :: t, но мне не удалось его использовать. – user1787222

+0

@ user1787222 Вы можете получить только элемент заголовка списка за один раз. Чтобы получить все элементы, вам нужно использовать рекурсию и каждый раз, когда вы получаете голову. –

+0

@ user1787222 Я обновил свой ответ. Если вы считаете, что это хорошо, отметьте мой ответ правильно –

1

Ваши шаблоны соответствуют спискам длины 0 ([]) и длины 1 ([x]). Компилятор сообщает вам, что есть другие длины, которые может иметь список, поэтому ваш шаблон, вероятно, неверен (это правда).

Я мог бы заметить, что это не ошибка, чтобы получить пустой список в качестве аргумента. Мышление таким образом значительно затруднит ответ на проблему. Если вы получите пустой список, правильным ответом будет пустой список пар.

1
let rec f e = function 
    | [] -> [] 
    | x::tl -> (e,x)::f e tl 

Или

let f e = List.map (fun x -> (e,x)) 

Тест

# f 1 [];; 
- : (int * 'a) list = [] 
# f 1 [10;20;30];; 
- : (int * int) list = [(1, 10); (1, 20); (1, 30)] 
Смежные вопросы