Применение и каррирование функций Haskell

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

Нет. Я перечитываю свои старые заметки ... и разочаровываюсь: - (

Проблема, которая заставила меня потерять веру в прошлый раз, была простой: перестановки целых чисел. Мои попытки завоевать Haskell приходят и уходят - уже дважды - и я ...

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

Нет. Я перечитываю свои старые заметки ... и разочаровываюсь: - (

Проблема, которая заставила меня потерять веру в прошлый раз, была простой: перестановки целых чисел. Мои попытки завоевать Haskell приходят и уходят - уже дважды - и я ...

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

Нет. Я перечитываю свои старые заметки ... и разочаровываюсь: - (

Проблема, которая заставила меня потерять веру в прошлый раз, была простой: перестановки целых чисел. то есть от списка целых чисел к списку списков - списку их перестановок:

[int] -> [[int]]

На самом деле это общая проблема, поэтому замена 'int' выше на 'a' все равно применима.

Из моего примечания:

Сначала я кодирую его самостоятельно, мне это удается. Ура!

Я отправляю свое решение своему хорошему другу - гуру Haskell, это обычно помогает учиться у гуру - и он отправляет мне это, что, как мне сказали, «выражает истинную силу языка, использование общие возможности для кодирования ваших потребностей ". Все ради этого, я недавно выпил kool-aid, пошли:

permute :: [a] -> [[a]]
permute = foldr (concatMap.ins) [[]]
   where ins x []     = [[x]]
         ins x (y:ys) = (x:y:ys):[ y:res | res <- ins x ys]

Хм. Давайте разберемся с этим:

bash$ cat b.hs
ins x []     = [[x]]
ins x (y:ys) = (x:y:ys):[ y:res | res <- ins x ys]

bash$ ghci
Prelude> :load b.hs
[1 of 1] Compiling Main             ( b.hs, interpreted )
Ok, modules loaded: Main.

*Main> ins 1 [2,3]
[[1,2,3],[2,1,3],[2,3,1]]

Хорошо, пока все хорошо. Мне потребовалась минута, чтобы понять вторую строку "ins", но нормально: Он помещает первый аргумент во все возможные позиции в списке. Круто.

Теперь давайте разберемся с foldr и concatMap. в "Real world Haskell" DOT была объяснена ...

(f . g) x

... как просто еще один синтаксис для ...

f (g x) 

И в коде, который прислал гуру, DOT использовалась из фолдера с "ins "функция как складка" коллапс ":

*Main> let g=concatMap . ins
*Main> g 1 [[2,3]]
[[1,2,3],[2,1,3],[2,3,1]]

Хорошо, поскольку я хочу понять, как DOT использует гуру, я пробую эквивалентное выражение в соответствии с определением DOT, (f. g) x = f (gx) ...

*Main> concatMap (ins 1 [[2,3]])

<interactive>:1:11:
     Couldn't match expected type `a -> [b]'
            against inferred type `[[[t]]]'
     In the first argument of `concatMap', namely `(ins 1 [[2, 3]])'
     In the expression: concatMap (ins 1 [[2, 3]])
     In the definition of `it': it = concatMap (ins 1 [[2, 3]])

Что!?! Зачем? Хорошо, я проверяю подпись concatMap и обнаруживаю, что ей нужны лямбда и список, но это просто человеческое мышление; как справляется GHC? Согласно приведенному выше определению DOT ...

(f.g)x = f(g x), 

... то, что я сделал, было правильным, с заменой:

(concatMap . ins) x y = concatMap (ins x y)

Почесывая голову ...

*Main> concatMap (ins 1) [[2,3]]
[[1,2,3],[2,1,3],[2,3,1]]

Итак ... Объяснение DOT очевидно было слишком упрощенно ... DOT должно быть достаточно умен, чтобы понять что мы на самом деле хотели, чтобы "инсайды" были съедены и "съели" первые аргумент - таким образом становится функцией, которая хочет работать только с [t] (и «перемежайте» их цифрой «1» во всех возможных позициях).

Но где это было указано? Как GHC узнал об этом, когда мы вызвали:

*Main> (concatMap . ins) 1 [[2,3]]
[[1,2,3],[2,1,3],[2,3,1]]

Подпись "ins" каким-то образом передала это ... политику "съесть мой первый аргумент"?

*Main> :info ins
ins :: t -> [t] -> [[t]]        -- Defined at b.hs:1:0-2

Я не вижу ничего особенного - "ins" означает функция, которая принимает 'т', список из 't', и переходит к созданию списка со всеми «перемежающимися знаками». Ничего о том, чтобы «съесть свой первый аргумент и убрать его».

Итак ... Я сбит с толку. Я понимаю (после часа разглядывания кода!), Что происходит, но ... Боже всемогущий ... Может, GHC пытается увидеть, сколько аргументов он может "отклеить"?

  let's try with no argument "curried" into "ins",
  oh gosh, boom, 
  let's try with one argument "curried" into "ins",
  yep, works,
  that must be it, proceed)

Опять же - уф .. .

И поскольку я всегда сравниваю языки, которые изучаю, с тем, что я уже знаю, как "ins" будут выглядеть в Python?

a=[2,3]
print [a[:x]+[1]+a[x:] for x in xrange(len(a)+1)]

[[1, 2, 3], [2, 1, 3], [2, 3, 1]]

Честно говоря, теперь ... что проще?

То есть, я знаю, что я новичок в Haskell, но чувствую себя идиотом ... Глядя на 4 строки кода в течение часа, и заканчивая предполагая, что компилятор ... пробует различные интерпретации, пока не находит что-то, что "щелкает"?

Цитата из Смертельного оружия: " fillMyMapWithStuff (myMap); // изменение значений ключей - мне нужно добавить постоянное значение к каждому ключу for (std :: map :: iterator mi = myMap ....

Учитывая

std::map<int,std::string> myMap;
fillMyMapWithStuff(myMap);

// modify key values - I need to add a constant value to each key
for (std::map<int,std::string>::iterator mi=myMap.begin(); mi != myMap.end(); ++mi)
{
    // ...
}

Какой хороший способ применить повторную индексацию? Должен ли я удалить старую запись и добавить новый с новым ключом и старым значением?

7
задан Justicle 7 October 2010 в 18:13
поделиться