Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

anyone know how to use a partially applied three argument function infix (haskell)

I want to apply a 3 argument function in different ways based on a boolean value (one of the arguments).

I'd like to be able to apply it in an infix manner so I can chain it (example below). something like the following but that actually works.

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

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

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

Do I need to have the Bool as the second variable? Or something else? I'm kind of lost.

P.S. the reason I wanted to do this was to have optional append function

like image 543
Roman A. Taycher Avatar asked Jun 15 '11 07:06

Roman A. Taycher


3 Answers

The infix notation for functions with more than two arguments is possible but not very nice. In your case, given

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

you can write

(True `f` 1) 3

It's much easier (as suggested by others) to write:

let ft = f True
let ff = f False

then you can do

1 `ft` 3 `ff` 5

If you want to use f you should write:

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

You can verify that

1 `ft` 3 `ff` 5 == (False `f` ((True `f` 1) 3)) 5
like image 120
MarcoS Avatar answered Nov 04 '22 11:11

MarcoS


You can use a reverse application operator to achieve a similar effect. However, for every operator fixity you will have to define its own pair of operators.

This works:

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"

And prints:

kojo
qwe

Here -| and |- brackets enclose left-associative infix expressions and =| and |= enclose right-associative expressions.

Be wary that as those are just pairs of independent operators, error messages when misusing them may be quite obscure.

like image 4
Rotsor Avatar answered Nov 04 '22 10:11

Rotsor


While infix expression syntax have been proposed, they have not been adopted, to the best of my knowledge.

You might consider using if then else ternary functions, like so:

infix 0 ?
(?) :: Bool -> (t, t) -> t
c ? (t, e) = if c then t else e
like image 3
Don Stewart Avatar answered Nov 04 '22 11:11

Don Stewart