f x y = 3 + y/x в произвольной форме

Я пытаюсь выяснить бессмысленную форму f x y = 3 + y/x в Хаскеле. Я думал, что это будет f = (3.0+) . flip (/), но ответ f2 = curry $ (3.0+) . (uncurry $ flip (/)), который так же, как f1 = curry ((3.0+) . (uncurry (flip (/))))Например, ответ, который я получил, но без спешки перед флипом и карри в начале.

Я вижу, как работает эта версия, но я не уверен, зачем нужны функции curry и uncurry, и почему моя версия не работает? Тип (3.0+) является a -> a, который я думал, будет работать, если вы кормите эту функцию с формой результата flip (/) через композицию функций, но (3.0+) . flip (/) 2 10 приводит к ошибке (почему?) и не дает 8. Разве это не избыточно, чтобы разархивировать, а затем снова карри?

1 ответ

Решение

Тип подписи . является (.) :: (b -> c) -> (a -> b) -> a -> c, Как видите, это работает только если вторая функция (в вашем ответе flip (/)) имеет один аргумент. Если у него есть два аргумента, мы можем использовать "оператор совы" (.) . (.), который имеет тип:

(.) . (.) :: (b -> c) -> (a -> a1 -> b) -> a -> a1 -> c

Или мы можем использовать карри. Используя uncurry :: (a -> b -> c) -> (a, b) -> c на flip (/) Часть, мы строим функцию:

uncurry (flip (/)) :: Fractional c => (c, c) -> c

так что теперь мы работаем с одним кортежем (таким образом, один аргумент), а затем мы используем curry :: ((a, b) -> c) -> a -> b -> c "распаковать" полученный первый аргумент снова.

альтернативы

Как обсуждалось ранее, мы можем использовать оператор owl:

   ((.) . (.)) (3.0+)  (flip (/))
-- ^   owl   ^

Или мы можем использовать синтаксически более сложную версию оператора owl:

((3 +) .) . flip (/)
Другие вопросы по тегам