Повторное использование функции Lambda в Haskell

Я должен взять этот код:

f x y z = x^3 - g (x + g (y - g z) + g (z^2))
 where g x = 2*x^2 + 10*x + 1

И переписать его без куда (или пусть).

Они хотят написать это с помощью лямбда-функции (\x ->...)

Я пытаюсь повторно использовать функцию Lambda в Haskell. Есть идеи?


person Asaf    schedule 19.11.2011    source источник
comment
f = flip flip ((1 +) . ap ((+) . (2 *) . (^ 2)) (10 *)) . (flip .) . ap ((.) . (.) . (.) . (-) . (^ 3)) (((ap id .) .) . flip flip (flip id . (^ 2)) . (liftM2 (liftM2 (+)) .) . (. ((ap id .) . (. flip id) . (.) . (-))) . (.) . (.) . (+)): f сделал бессмысленным лямбдабот   -  person fuz    schedule 19.11.2011


Ответы (6)


Как намекает bravit, вы можете переписать нерекурсивное let с помощью лямбды следующим образом:

let x = A in B     ==>     (\x -> B) A 

где x — переменная, а A и B — выражения.

person hammar    schedule 19.11.2011
comment
Что мне кажется забавным в этом трюке, так это то, что это на самом деле стандартная практика в Javascript, поскольку только функции могут вводить там блок области видимости. - person hugomg; 19.11.2011
comment
Я до сих пор не уверен, что понимаю, как его можно использовать повторно - person Asaf; 19.11.2011
comment
@Asaf: Вы можете ссылаться на x несколько раз в B. Например, возьмем (\x -> x + x) 3. Это эквивалентно 3 + 3, за исключением того, что вам нужно было написать 3 только один раз. - person hammar; 19.11.2011
comment
@Asaf Вот подсказка: помните, что аргументы лямбда-выражения могут сами быть функциями. - person Daniel Wagner; 19.11.2011

Чтобы повторно использовать что-то, вы можете сделать это аргументом для чего-то.

person bravit    schedule 19.11.2011

Я думаю, что намерение — это то, на что намекает bravit.
Умный обходной путь, который следует букве закона, связывает g с case ;)

person Daniel Fischer    schedule 19.11.2011
comment
Другим умным решением было бы сделать g функцией верхнего уровня, поскольку она ничего не закрывает из f :) - person hammar; 19.11.2011

Чтобы расширить подсказки Хаммара и Бравита, вашему решению потребуется не одна лямбда, а две, одна из которых будет очень похожа на g, а другая — на вторую половину f.

person Nate    schedule 19.11.2011

Использование лямбда-исчисления g равно (\x -> 2*x^2 + 10*x + 1)

Поэтому вам нужно заменить g на это в f x y z = x^3 - g (x + g (y - g z) + g (z^2))

$> echo "f x y z = x^3 - g (x + g (y - g z) + g (z^2))" | sed -r -e 's/g/(\\x -> 2*x^2 + 10*x + 1)/g'
f x y z = x^3 - (\x -> 2*x^2 + 10*x + 1) (x + (\x -> 2*x^2 + 10*x + 1) (y - (\x -> 2*x^2 + 10*x + 1) z) + (\x -> 2*x^2 + 10*x + 1) (z^2))

Я просто шучу, извини.

person ДМИТРИЙ МАЛИКОВ    schedule 19.11.2011
comment
Я уверен, что его инструкторы были бы менее чем взволнованы этим ответом;) - person Nate; 19.11.2011
comment
Это именно тот ответ, который я бы дал. Насколько я знаю, вопрос сводится к следующему: возьми этот идиоматический код и ухудши его, просто чтобы доказать, что ты знаешь X. Если учитель хочет проверить, знаю ли я X, он должен задать вопрос, где X на самом деле полезно/нужно. - person Rafael Caetano; 07.03.2012

Этот вопрос кажется мне любопытным и интересным. Итак, я пытаюсь понять, что такое лямбда-исчисление, найти ответ и хочу показать его ОП (на самом деле все подсказки уже были показаны, спойлер).

Во-первых, давайте попробуем переопределить f:

λ> let f = (\g x y z -> x^3 - g(x + g(y - g z) + g(z^2)))
f ::
  (Integer -> Integer) -> Integer -> Integer -> Integer -> Integer

Итак, у нас есть функция, которая получает функцию и 3 числа и возвращает ответ. Используя curring, мы можем добавить определение g прямо здесь, например f_new = f g:

λ> let f = (\g x y z -> x^3 - g(x + g(y - g z) + g(z^2))) (\x -> 2*x^2 + 10*x + 1)
f :: Integer -> Integer -> Integer -> Integer

Были сделаны. Давайте проверим это:

λ> f 0 0 0
-13

Ответ правильный.

UPD:

В этих примерах let — это просто способ объявить функцию в интерпретаторе, поэтому окончательный ответ:

f :: Num a => a -> a -> a -> a
f = (\g x y z -> x^3 - g(x + g(y - g z) + g(z^2))) (\x -> 2*x^2 + 10*x + 1)
person ДМИТРИЙ МАЛИКОВ    schedule 20.11.2011