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 (/)