Reputation: 573
Having the function:
f : Int -> Int -> Int
f a b =
a + b
is there a way to pipe both a and b?
Iv'e got only this far, but I would like to know if there is a way to get rid of the brackets:
main =
1 |> (2 |> f) |> toString |> text
Upvotes: 3
Views: 3133
Reputation: 10239
The |>
pipe evaluates the left side first, which is what you want, and applies the first argument to the second, which is not what you want.
The <|
pipe evaluates the right side first, which is not what you want, and applies the second argument to the first, which is not what you want.
You can get round it with lambdas that invert the function application. Like this
add a b = a + b
add
|> \f -> f 2
|> \f -> f 3
-- outcome: 5
Or you can write a helper function
invert v f = f v
add
|> invert 2
|> invert 3
Upvotes: 1
Reputation: 9885
You can achieve a similar flow like this:
1 :: 2 :: [] |> List.foldl f 0 |> toString |> text
The idea is to use ::
to create a List
containing the arguments. Then, use foldl
to apply the function f
to the arguments.
Of course, there are a number of superfluous items in the syntax: the empty List
and the starting value needed by foldl
. Continuing with your example function, you can use composition to hide the starting value:
let
g = List.foldl f 0
in
1 :: 2 :: [] |> g |> toString |> text
The downside is you'd still have a starting value to deal with, which you probably wish was simply the head of the list (ex. 1). But, if you try to use the head of the list as the starting value, you'd end up with another problem:
If there's no starting value (an empty list) then fold cannot return anything, and all Elm functions have a return value.
Regardless, hopefully this approach will help.
Upvotes: 0
Reputation: 6366
Don't pipe for piping's sake. It's a lot cleaner to say 1 |> f 2 |> toString |> text
than what you have in your example. The argument that gets piped is frequently the data structure, since by convention it's always the last argument. Let's look at a more realistic example:
"40"
|> String.toInt
|> Maybe.map (\n -> n + 2)
|> Maybe.withDefault 2
The direct arguments (the lambda, 2
) affect the operation while the data structure (a Maybe Int
for part of the chain) is piped though. Contrast: Maybe.withDefault 2 (Maybe.map (\n -> n + 2) (String.toInt "40"))
. This ugly version isn't even faster, since pipes are optimized by the compiler.
If you pipe in this style, of transformations on a data structure, you will not need to pipe two items in.
Upvotes: 4
Reputation: 2256
I would imagine not. I've never seen it. The reason it's so unlikely is that technically, all elm functions only take one argument. But what about things like this?
add 1 2 3
Well, Elm actually curry's the function, and returns an anonymous function after the first argument that takes the second argument, and that takes the second argument and returns a third argument. If you've ever wondered why the type annotations look like there's no seperation between the multiple arguments and the return statement .....
add : Int -> Int -> Int
... that's because there's not!
Upvotes: 0
Reputation: 36030
Although it may not satisfy you, one simple possibility is:
(1, 2) |> uncurry f
Upvotes: 7