Попытка улучшить текущий уродливый кусок кода в haskell, работающий со списками - PullRequest
2 голосов
/ 02 декабря 2010

Я пытаюсь реализовать функцию в Haskell, которая будет принимать произвольный список целых чисел xs и целое число k и возвращает набор списков с k во всех возможных позициях.

Например, для xs = [0, 1] и k = 2 у нас будет

myFunction [0, 1] 2 = [ [2, 0, 1], [0, 2, 1], [0, 1, 2] ]

Я реализовал это как

putOn xs x i = (take i xs) ++ (x:(drop i xs))
putOnAll xs x = map (putOn xs x) [0..(length xs)]

, но я чувствую, что должны быть другиеумные способы достичь того же.Мой код выглядит так, будто кто-то пытается убить ошибку с помощью ракеты.Может ли кто-нибудь сделать предположения о способах сделать что-то умное, чем этот кусок кода?

Спасибо

Ответы [ 4 ]

3 голосов
/ 25 мая 2011

Вы также можете использовать стрелки:

import Control.Arrow

ins x = inits &&& tails >>> second (map (x:)) >>> uncurry (zipWith (++))

С помощью &&& ("разветвление") вы даете один аргумент двум функциям, что дает пару результатов. Вы можете использовать >>> («и затем») для переключения нормального порядка приложения, позволяя иметь цепочки операций слева направо. second работает только на второй части пары. Наконец, вам нужно uncurry для рекомбинации результатов, передавая пару в функцию, ожидающую два отдельных аргумента.

3 голосов
/ 02 декабря 2010

Взято из этого вопроса :

ins x []     = [[x]]
ins x (y:ys) = (x:y:ys):[ y:res | res <- ins x ys]
1 голос
/ 02 декабря 2010
ins x xs = zipWith (\ a b -> a ++ (x:b)) (inits xs) (tails xs)

[Править] Бах, слишком поздно, Луки избил меня

Однако, здесь версия без лямбды:

ins x xs = zipWith (flip (++).(:) x) (tails xs) (inits xs) 
1 голос
/ 02 декабря 2010

Мне очень нравится ясность этого определения:

ins x ys = zipWith (\pre post -> pre ++ [x] ++ post) (inits ys) (tails ys)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...