Безточечный стиль с инфиксной нотацией

Здравствуйте, есть ли способ написать безточечный стиль при использовании инфиксной нотации?

f::Int->Int->Int->Int
f a b=(+) (a+b)

Почему вы не можете сделать что-то подобное?

 f::Int->Int->Int->Int
 f a b=(a+b) +

      or

 f a b= (a+b) `+`

Не можете ли вы комбинировать операторы в стиле без точки, например, например?

ptfree::Int->Int->Int->Int
ptfree=(+) (+)

Я имею в виду, что вы можете обрезать аргументы таких функций, как fold, но почему бы и нет для аргументов оператора?


person Bercovici Adrian    schedule 14.06.2018    source источник
comment
Вы имеете в виду полностью бесточечное? Единственный полностью бесточечный пример, который вы привели, - это последний.   -  person David Young    schedule 14.06.2018
comment
Да, можно ли сделать это совершенно без очков?   -  person Bercovici Adrian    schedule 14.06.2018
comment
Что вы собираетесь делать в последних трех примерах? Они принимают только 2 аргумента в соответствии с сигнатурами типов.   -  person David Young    schedule 14.06.2018
comment
Я отредактировал, извините!   -  person Bercovici Adrian    schedule 14.06.2018


Ответы (2)


Что ж, поскольку вам нужно передать два параметра, мы можем использовать то, что известно как "оператор удивленной совы". В основном это набор параметров. Итак, мы можем использовать:

f = ((.).(.)) (+) (+)

Или мы можем более встроить оператор, например:

f = ((+) .) . (+)

Оператор совы ((.).(.)) f g в основном является сокращением от \x y -> f (g x y)

Как это работает?

Каноническая форма "оператора удивленной совы":

= ((.) . (.))
------------- (canonical form)
  (.) (.) (.)

Итак, теперь мы можем заменить (.)s соответствующими лямбда-выражениями:

(\f g x -> f (g x)) (.) (.)

Итак, теперь мы можем выполнить некоторые замены:

   (\f g x -> f (g x)) (.) (.)
-> (\x -> (.) ((.) x))
-> (\x -> (\q r y -> q (r y)) ((.) x))
-> (\x -> (\r y -> ((.) x) (r y)))
-> (\x r y -> ((.) x) (r y))
-> (\x r y -> ((\s t u -> s (t u)) x) (r y))
-> (\x r y -> (\t u -> x (t u)) (r y))
-> (\x r y -> (\u -> x ((r y) u)))
-> \x r y u -> x ((r y) u))
-> \x r y u -> x (r y u)

Таким образом, в основном это означает, что наш оператор удивленной совы равен:

surprised_owl :: (y -> z) -> (a -> b -> y) -> a -> b -> z
surprised_owl f g x y = f (g x y)  -- renamed variables

И если мы теперь специализируем это с предоставленными функциями (два раза (+)), мы получим:

f = surprised_owl (+) (+)

so:

f x y = (+) ((+) x y)
person Willem Van Onsem    schedule 14.06.2018
comment
Спасибо за ваш ответ ! - person Bercovici Adrian; 14.06.2018

Вы должны составить (+) с (+) дважды, чтобы это было полностью бесточечным: f = ((+) .) . (+)

Напомним, что композиция определяется как

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

или, что то же самое:

(f . g) = \x -> f (g x)

Итак, если вы посмотрите на композицию f = ((+) .) . (+) и пойдете назад, используя определение (.):

f       = ((+) .) . (+)
f       = \x -> ((+) .) ((+) x)          -- definition of (.)
f       = \y -> (\x -> (+) (((+) x) y))  -- definition of (.)
f x y   = (+) (((+) x) y)                -- a simpler way to write this
f x y z = (+) (((+) x) y) z              -- explicitly add in the final argument (eta expansion)
f x y z = ((+) x y) + z                  -- rewrite as infix
f x y z = (x + y) + z                    -- rewrite as infix

и вы видите, что в итоге мы пришли к тому, что начали до того, как попытались сделать это бесточечным, поэтому мы знаем, что это определение работает. Пройдя описанные выше шаги в обратном порядке, примерно снизу вверх, вы можете получить представление о том, как найти такое бесточечное определение функции, например f.

Когда вы «опускаете» несколько аргументов с «конца», как это, вы обычно должны составлять несколько раз. Работа с несколькими похожими функциями должна помочь создать интуицию для этого.

Примечание. Обычно я бы не рекомендовал использовать такого рода бесточечное (когда это усложняет ситуацию) в производственном коде.

person David Young    schedule 14.06.2018
comment
Спасибо за ваш ответ, сэр! - person Bercovici Adrian; 14.06.2018