Функция Haskell, которая альтернативно применяет унарные функции ввода

Я пытаюсь написать функцию Haskell, которая принимает две унарные функции (f и g) и список чисел (ns) и альтернативно применяет эти входные функции f и g к элементам введенного списка.

Например:

func double square [2, 3, 4, 5, 6]

вернется

[4, 9, 8, 25, 12]

Я использую WinGHCi для своего компилятора. Приветствуется любая помощь в написании этой функции, спасибо.


person T-Bird    schedule 09.12.2015    source источник
comment
Проверьте zipWith и cycle.   -  person luqui    schedule 09.12.2015
comment
См. http://stackoverflow.com/questions/17383169/haskell-double-every-2nd-element-in-list/17383354#17383354   -  person Thomas M. DuBuisson    schedule 09.12.2015
comment
Я стараюсь не использовать библиотечные функции, и не понимаю, чем поможет zipWith ...   -  person T-Bird    schedule 09.12.2015
comment
Почему бы не использовать библиотечные функции?   -  person Rodrigo Ribeiro    schedule 09.12.2015
comment
@ T-Bird: Избегать библиотечных функций - не лучшая идея. Хороший стиль функционального программирования включает в себя разделение проблем на более мелкие части и их решение с помощью универсальных многоразовых функций, которые можно найти в стандартных библиотеках. Итак, лучшая стратегия - (а) использовать стандартные библиотечные функции для решения вашей проблемы, а затем (б) написать свои собственные версии функций в качестве дополнительного упражнения. И это рекурсивное решение, поскольку на шаге (b) вы можете использовать другие библиотечные функции ...   -  person Luis Casillas    schedule 09.12.2015


Ответы (3)


Если вы не хотите использовать какие-либо библиотечные функции, вы можете сделать это с помощью рекурсии:

func _ _ []     = []
func f g (x:xs) = f x : func g f xs
person Michael Szvetits    schedule 09.12.2015
comment
В качестве однострочного: interMap f g xs = foldr (\x r f g -> f x : r g f) (\_ _ -> []) xs f g. - person user3237465; 09.12.2015

Расширение комментария @ luqui:

func f1 f2 l = zipWith ($) (cycle [f1, f2]) l

Если вы не хотите использовать библиотечные функции, просто посмотрите их реализации, они довольно простые.

person fjarri    schedule 09.12.2015
comment
Обратите внимание, что в этом случае вы также можете использовать id вместо ($), что, вероятно, упрощает чтение. - person Alberto Schiabel; 09.02.2020
comment
Более того, вы можете полностью отбросить l (сделав его неявным параметром), чтобы получить более короткое выражение. - person Alberto Schiabel; 09.02.2020

Просто простое решение ...

fun :: (a -> b) -> (a -> b) -> [a] -> [b]
fun f g = reverse . snd . foldl step (0,[])
          where
             step (c,ac) x = (c + 1, (if even c then f x else g x) : ac)

Поскольку вы не хотите использовать библиотечные функции, вы можете воспроизвести тот же результат без использования foldl. Идея проста - использовать счетчик, чтобы узнать, какая позиция четная, а какая нет.

Изменить: я немного запутал свой аккумулятор. Теперь это правильно.

person Rodrigo Ribeiro    schedule 09.12.2015
comment
Целью было избежать библиотечных функций по неизвестным причинам. - person Michael Szvetits; 19.02.2016