Инфиксная запись в Haskell с двумя аргументами слева - PullRequest
0 голосов
/ 24 февраля 2019

В Haskell, инфиксная запись позволяет нам делать следующее:

divide :: Double -> Double -> Double
divide x y = x / y

foo = divide 10.0 3.0
bar = 10.0 `divide` 3.0 -- infix
-- foo and bar are equivalent

Можно ли использовать / определить инфиксную запись, которая будет принимать 2 аргумента слева?

sumAndDivideBy :: Double -> Double -> Double -> Double
sumAndDivideBy x y z = (x + y) / z

foo2 = sumAndDivideBy 3.0 5.0 2.0
bar2 = 3.0 `sumAndDivideBy` 5.0 $ 2.0 -- works but not what I wan't
bar3 = 3.0 5.0 `sumAndDivideBy` 2.0   -- does not work - impossible?

Ответы [ 2 ]

0 голосов
/ 24 февраля 2019

Почему бы не обмануть?

sumAndDivideBy :: (Double, Double) -> Double -> Double
sumAndDivideBy (x, y) z = (x + y) / z

В ghci:

> (3,5) `sumAndDivideBy` 2
4.0
0 голосов
/ 24 февраля 2019

Короткий ответ: нет, вы не можете сделать это так, как просите.

Насколько я понимаю, если у вас есть функция f :: x -> y -> z.затем вы можете написать его приложения в виде

f x0 y0

или

x0 `f` y0

, и они означают одно и то же.

В случае вашей функцииsumAndDivideBy :: Double -> Double -> Double -> Double, из-за карри, что эквивалентно Double -> (Double -> (Double -> Double)), если мы полностью откровенны.Позвольте мне написать, что в промежуточной форме между ними:

sumAndDivideBy :: Double -> Double -> (Double -> Double)

Это в точности соответствует схематической форме, которую я дал выше, с x и y, равными Double и z длятип функции Double -> Double.Это означает, что вы действительно можете использовать sumAndDivideBy в инфиксной форме, точно так же, как вы использовали в предпоследней строке вашего примера.В общем случае вы можете сделать это с любой функцией с более чем 2 аргументами, но форма «инфикс» работает только в том случае, если она идет между первым и вторым аргументами.

Конечно, из-за каррирования вы можете понять,sumAndDivideBy 3.0 сама по себе является функцией Double -> Double -> Double, которую вы можете использовать в инфиксной форме, в той же «позиции», в которой вы хотите, чтобы она находилась. Таким образом, вы можете сделать это:

sumWithThreeAndDivide = sumAndDivideBy 3.0
foo = 5.0 `sumWithThreeAndDivide` 2.0

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

Я не уверен, к чему именно вы стремитесь,учитывая, что ваш пример может быть очень естественным образом воспроизведен с помощью функции divide, как вы показали, как

(3.0 + 5.0) `divide` 2.0

или, конечно, поскольку divide идентичен (/), простоделать 3.0 + 5.0 / 2.0, как я полагаю, вы, естественно, сделали бы.

...