У меня есть список 'a и one' b и функция типа 'a -> 'b-> 'c
. Я пытаюсь применить функцию к каждому элементу списка с b, который у меня уже есть, и составить список «c». В haskell я бы сделал что-то вроде zipWith(foobar) a-list (replicate (length a) b).
Каков эквивалентный способ сделать это в OCaml?Эквивалент zipwith от haskell в OCaml
ответ
Ну, в вашем примере вы на самом деле не нужно zipWith
, вы можете использовать простой map
:
List.map (fun a -> f a b) a_list
Это было бы более эффективно, чем List.map2
(эквивалент zipWith
), потому что OCaml не обрабатывает списки так же, как Haskell, поэтому построение фиктивного списка только ради итерации на самом деле не стоит.
"List.map2" является эквивалентом Хаскеля "zipWith"
val map2 : ('a -> 'b -> 'c) -> 'a list -> 'b list -> 'c list
op имеет только один 'b', а не' list 'b' –
Это отвечает на вопрос, как указано в заголовке, что полезно для будущих посетителей. –
@MartinJambon hmm Я согласен –
Эквивалент в OCaml будет:
open Core_kernel.Std
let replicate n b = List.init n ~f:(fun _ -> b)
List.(map2_exn a (replicate (length b) b) ~f:your_function)
Этот код возникает несколько вопросов, однако. Например, вы уверены, что хотите, чтобы список был вторым аргументом вашей функции? И в чем причина дублирования второго аргумента, вместо того, чтобы передавать его как свободную переменную в вашу функцию, как предположил @PatJ. И это не все о ленивой и нетерпеливой оценке. В Haskell вам все равно нужно пройти по списку, и b
будет пройден дважды. Тот факт, что вычисление является ленивым, не означает, что он будет быстрее, когда он будет оценен.
Но, тем не менее, библиотека Core OCaml предоставляет ленивый список с именем Sequence
, который похож на Haskell's. Код будет таким же, по модулю имени модуля, т. Е. Просто замените List
на Sequence
.
Ну, я мало знаю о поведении Хаскелла и полагаю, что он был оптимизирован без проверки. (ленивый я: -p) – PatJ
Я думаю, что описание проблемы путают ответы. Вы должны сказать «список» a и один «b», если я правильно понимаю. Кроме того, если это так, то даже в haskell вам не нужно 'zipWith', простая« карта »может решить вашу проблему. –
Yikes. Скажите, что вы на самом деле никогда не писали 'zipWith f a (replicate (length a) b)'. Перемещение 'a' вдвое больше, чем это очень плохо для потокового поведения. Гораздо лучше написать 'zipWith f a (repeat b)'. – Carl
Это было в прошлом, когда я впервые изучал Хаскелл, но да, да. –