что не так с моей несправедливой реализацией? - PullRequest
2 голосов
/ 05 апреля 2011

Я пытаюсь выяснить, ПОЧЕМУ я получаю ошибку ниже, чем я заинтересован в правильной реализации моего метода.

У меня есть следующий код f #, который должен расцепить списоккортежей в список, содержащий все элементы в кортежах, например:

let unpair l =
    let rec loop acc l =
        match l with
        | [] -> acc
        | (x,y)::tl ->
            loop (acc @ x @ y) tl
    loop [] l

//should print:
// [1 2 3 4 5 6]

printf "["
List.iter (printf "%A") (unpair [(1, 2); (3, 4); (5, 6)])
printfn "]"

Я получаю следующую ошибку для каждого из моих целых при вызове unpair: ожидалось, что это выражение будет иметь тип 'список, но здесьимеет тип int

Почему он ожидает список?

Ответы [ 2 ]

4 голосов
/ 05 апреля 2011

Проблема в следующем выражении

acc @ x @ y

@ используется для объединения list значений вместе, но здесь x и y набираются в int.Вы ищете оператор ::, который будет добавлять элементы в список.Кроме того, вы строите список в обратном направлении в этом выражении.Используйте следующее, и это должно решить вашу проблему

x :: y :: acc
2 голосов
/ 05 апреля 2011

Как объясняет JaredPar, вам нужно использовать x::acc для добавления элементов в аккумулятор. Если вы хотите добавить элементы в конец, вы можете написать acc @ [x], но это очень неэффективно, так как необходимо скопировать весь список для каждого отдельного элемента.

Обычное решение - добавить элементы в начало списка, а затем перевернуть список в конце обработки:

let unpair l =
    let rec loop acc l =
        match l with
        | [] -> List.rev acc     // NOTE: Reverse the list here
        | (x,y)::tl ->
            loop (y::x::acc) tl  // Add elements to the front  
    loop [] l

Это намного эффективнее, чем использование acc @ [x], потому что он продолжает добавлять элементы вперед (что занимает лишь небольшое постоянное время), а затем создает одну копию всего списка в конце.

Эту же функцию можно также эффективно и эффективно реализовать с помощью выражений последовательности:

let unpair l =
  [ for x, y in l do
      yield x
      yield y ]
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...