кто-нибудь знает, как использовать частично примененную трех аргументную функцию infix (haskell) - PullRequest
4 голосов
/ 15 июня 2011

Я хочу применить функцию с тремя аргументами по-разному в зависимости от логического значения (один из аргументов).

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

f :: Bool -> a -> a -> a

f True  i j = i
f False i j = j

... y `(f True)` z `(f False)` b

Нужно ли иметь Bool в качестве второй переменной?Или что-то другое?Я немного растерялся.

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

Ответы [ 5 ]

6 голосов
/ 15 июня 2011

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

f :: Bool -> a -> a -> a
f True i j = i
f False i j = j

, вы можете написать

(True `f` 1) 3

Гораздо проще (как предложено другими) написать:

let ft = f True
let ff = f False

, тогда вы можетеdo

1 `ft` 3 `ff` 5

Если вы хотите использовать f, вы должны написать:

(False `f` ((True `f` 1) 3)) 5

Вы можете проверить, что

1 `ft` 3 `ff` 5 == (False `f` ((True `f` 1) 3)) 5
4 голосов
/ 15 июня 2011

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

Это работает:

infixl 5 -|
(-|) :: a -> (a -> b) -> b
(-|) = flip ($)

infixl 5 |-
(|-) :: (a -> b) -> a -> b
(|-) = ($)

infixr 5 =|
(|=) :: (a -> b -> c) -> b -> (a -> c)
(|=) = flip

infixr 5 |=
(=|) :: a -> (a -> c) -> c
(=|) = (-|)

f b x y = if b then x else y

main = do
    putStrLn $ "qwe" -| f True |- "asd" -| f False |- "kojo"
    putStrLn $ "qwe" =| f True |= "asd" =| f False |= "kojo"

И отпечатки:

kojo
qwe

Здесь -| и |- заключают в скобки левоассоциативные инфиксные выражения, а =| и |= заключают правоассоциативные выражения.

Будьте осторожны, так как это просто пары независимых операторов, сообщения об ошибках при неправильном их использовании могут быть весьма неясными.

3 голосов
/ 15 июня 2011

Хотя синтаксис выражений инфиксов был предложен, насколько я знаю, они не были приняты

Вы можете рассмотреть возможность использования if then else троичных функций, например:

infix 0 ?
(?) :: Bool -> (t, t) -> t
c ? (t, e) = if c then t else e
1 голос
/ 15 июня 2011

Ну, с одной стороны, f будет иметь тип f :: Bool -> a -> a -> a

См. http://www.haskell.org/haskellwiki/Infix_operator#Using_prefix_functions_with_infix_notation для получения дополнительной информации об использовании префиксных функций в настройке инфикса.

Надеюсь, кто-то еще умнее и сможет объяснить, почему

1 `f True` 3 

не работает, так как

ft = f True
1 `ft` 3

работает нормально, и это, кажется, нарушает ссылочную прозрачность ...

Казалось бы, не существует "хорошего", простого способа сделать это, но я уверен, что есть какой-то паттерн более высокого уровня, который подходит, или вы могли бы сделать что-то с, например, zipWith или сгибами. ...

0 голосов
/ 15 июня 2011

Зачем вам вообще нужна логическая функция?Если значение никогда не используется, почему бы не определить f как

f :: a -> a -> a  
f i j  
i `f` j

Если логическое значение действительно необходимо, то, как предложил Pvital, создайте ftrue и ffalse и используйте их.

...