PureScriptでパイプライン演算子に相当するapplyFlipped関数と#演算子

## 関数適用

普及しているプログラミング言語の多くで、関数適用は`関数名(引数)`という表記が用いられています。

PureScriptにおいて、関数適用は`関数名 引数`という形で関数適用ができます。

例えば「整数を2倍する関数」として`double`関数があるとき、

```haskell
double :: Int -> Int
double x = x * 2
```

`double 10`という表記で`double`関数に`10`という値を適用できます。

```haskell
> double 10
20
```

「10という値を`double`関数で2倍して標準出力する」プログラムの場合は、

```haskell
module Main where

import Prelude

import Effect (Effect)
import Effect.Console (log)

double :: Int -> Int
double x = x * 2

main :: Effect Unit
main = log (show (double 10))
```

となります。

`main = log (show (double 10))`の部分が関数適用している箇所になります。

ここのカッコ（`()`)は関数適用のためのものではなく、関数適用を優先させるために用いているものです。

このカッコが無い場合は「`log`関数への引数として`show`関数、`double`関数、`10`を与える」という意図しない意味になってしまい、型エラーとなるためです。

実際にカッコがない状態で以下のように書くと、

```haskell
-- 型エラーになる書き方
main = log show double 10
```

「（`log`関数の引数の型）`String`に`t0 -> String`の型は合わない」という以下のようなエラーになります。

```
  Could not match type

    t0 -> String

  with type

    String


while checking that type forall (@a :: Type). Show a => a -> String
  is at least as general as type String
while checking that expression show
  has type String
in value declaration main

where t0 is an unknown type
```

エラーの理由は、`log`関数の引数として`show`関数自体を渡そうとしてしまっているためです。

また、関数適用の方法として`$`演算子を使うという方法があります。

`$`演算子を使うと、先ほどのカッコを使って関数適用を優先させる必要が無くなります。

```haskell
main = log $ show $ double $ 10
```

PureScriptはHaskellと同様に演算子は関数でもあり、演算子は2引数の関数適用の中置記法でしかないので、`$`演算子の実態は`$`関数であり、通常の関数適用が可能です。

PureScriptでは記号を用いた関数名を中置記法以外の方法で関数適用する場合は、その記号をカッコで囲う必要があります。

```haskell
> -- ($)関数を普通の関数として関数適用してみる（通常はこのような書き方はしない）
> ($) double 10
20
```

そして、この`$`関数は`apply`という関数の別名（エイリアス）でもあるので、`apply`関数を使った関数適用が可能です。

`apply`関数は`Data.Function`モジュールで定義されており、`apply`関数を直接使用するには明示的に`Data.Function`モジュールの`apply`関数を読み込む必要があります。

```haskell
> import Data.Function (apply)
> -- apply関数を使った関数適用（通常はこのような書き方はしない）
> apply double 10
20
```

また、記号ではない通常の関数であっても関数名を「`」（バッククオート）で囲うと中置記法で関数適用ができます。

```haskell
> import Data.Function (apply)
> double `apply` 10
20
```

## applyFlipped関数と#演算子

F#というプログラミング言語では、一般的な関数適用と書き順が逆になった`引数 |> 関数名`という書き方で関数適用をする「パイプライン演算子」というものがあります。

PureScriptでも、このパイプライン演算子と同様に「引数のあとに関数名を書く」という表記で関数適用をする`applyFlipped`関数というのがあります。

🔗[applyFlipped \- Data\.Function \- purescript\-prelude \- Pursuit](https://pursuit.purescript.org/packages/purescript-prelude/6.0.1/docs/Data.Function#v:applyFlipped)

> applyFlipped :: forall a b. a -> (a -> b) -> b
> Applies an argument to a function. This is primarily used as the (#) operator, which allows parentheses to be omitted in some cases, or as a natural way to apply a value to a chain of composed functions.

この`applyFlipped`関数は、関数適用させる関数の引数としての値と、関数適用させる関数の2つを引数として取ります。

通常の関数適用で書くと、以下のようになります。

```
applyFlipped 引数 関数
```

`apply`関数と異なり「引数」「関数」という順番になっています。

先ほどの`double`関数の例だと以下のようになります。

```haskell
> applyFlipped 10 double
20
```

中置記法で書くと以下のようになります。

```
引数 `applyFlipped` 関数
```

`double`関数の例だと以下のようになります。

```haskell
> 10 `applyFlipped` double
20
```

また、`applyFlipped`関数には別名として`#`が定義されており、これを中置記法で書くと以下のようになります。

```
引数 # 関数
```

```
> 10 # double
20
```

「10という値をdouble関数で2倍して標準出力する」プログラムの例で、この`applyFlipped`関数としての`#`演算子を用いると以下のようになります。

```haskell
module Main where

import Prelude

import Effect (Effect)
import Effect.Console (log)

double :: Int -> Int
double x = x * 2

main :: Effect Unit
main = 10 # double # show # log
```

`10 # double # show # log`の部分が`#`演算子を用いた関数適用になっており、F#のパイプライン演算子を使った関数適用のような見た目になっています。

```fsharp
// F#の例
let double x = x * 2
10 |> double |> printfn "%d"
```

PureScriptで`#`演算子を使うことで、データと関数適用の順番が左から右へと流れるような見た目となり、データの流れが見通しやすくなるかもしれないです。

しかし、一般的には通常の`$`演算子が使われることの方が多いようです。