🏄

Elm開発者から見たPureScript入門の感想

2022/12/18に公開

https://qiita.com/advent-calendar/2022/purescript

18日目の記事になります。

普段Elmを触っている開発者が、同じ純粋関数型であるPureScriptに触れたら、どう感じたかをまとめた記事です。大きく、気になった点と素晴らしいなーと思った2つの軸で挙げていきたいと思います。

気になった点

完璧な言語はありません。言語は人が作るものですから。ただ、改善して良くなるものは改善していきたいので、気になった点は挙げていって、微力ながら力になれるところはなっていきたいなと思います。

ドキュメントが古い

ドキュメントが少ないは、マイナー言語の宿命だと思います。ただ、Elm同様に関数のシグネチャさえわかり、さらにソースコードの定義さえ見てしまえば、大体の動きはわかります。

ただ、ドキュメントが古いケースは誤解して進んでしまうことがあるので危険です。特に日本人の場合は日本語のドキュメントが目に入ってしまうので、例えば今はspagoと呼ばれるビルドツールを使うのが主流ですが、Bowerの記述があるドキュメントや古いmainの定義のドキュメントなどがまだ目に触れやすい場所にあるなという印象です。

どのパッケージが必須なのかがわからない

PureScriptはパッケージが豊富であり、パッケージは細かく分割されています。それ自体は良いことであり、思想としての一つのあり方なのだなと思います。ただ、明らかに普段使うだろうパッケージがなんであるかわからない・毎回インストールする手間がかかる点が気になりました。

spago initをすると、spago.dhallに初期パッケージが記載されますが、以下の3つのみがpre-installされます。これらのパッケージで十分に開発がスタートできるとかというとそうではありません。

dependencies = [ "console", "effect", "prelude" ]

私自身はまだまだPureScript初心者なので、何があれば必要十分なのか把握できていませんが、以下くらいのパッケージは必要・・・いや、使っている人にはもっと必要と思うケースが多いのでは無いのかなと思います。また、なぜこれらのパッケージを使うべきなのか これをするときはこの構成などのドキュメントやスターターは用意されていると嬉しいのかな?と思いました。

  • aff
  • arrays
  • debug
  • either
  • maybe
  • tuples

https://pursuit.purescript.org/

spagoがぶちまける

spagoはPureScruptのビルドツールです。spago initをしたときに様々なファイル群が作られます。

こういったビルドツールのセットアップは、新しいディレクトリが作られてそこにファイルを展開するケースとその場でファイルを展開するケースの2タイプに分かれると思い好みがあると思いますが、私は前者の方が好みです。

前者は、ミスった時に mv project .. だけのリカバリーで済みますが、後者は、mvやrmの対象が増えます。もっと丁寧なものは、新しいディレクトリが作られる上でさらにディレクトリ名を対話型で聞いてくれるようなタイプだと作る途中でディレクトリが作られるのだなと予測がつきます。spagoは、無言でファイルをぶちまけるので、ちょっと丁寧な作りとは言い難いと思います。

割と実行時例外が起きる

Haskellなどは古いsafeではないモジュールを利用すると、例えばListのheadなどを取ったときに実行時例外が起きたりします。

ElmやPureScriptは後発の言語のため、headは、以下のようなシグネチャになっており、Maybeとなるため型として安全です。

head :: forall a. Array a -> Maybe a

https://pursuit.purescript.org/packages/purescript-arrays/7.1.0/docs/Data.Array#v:head

これはとても安心だ、と思ったのですがPureScriptの場合、FFI(他言語関数インターフェース)があります。具体的には、JavaScriptのコードをラップすることができます。これが柔軟であり、悩ましいポイントでもあります。JavaScriptはナチュラルに例外を吐いてしまう上にPureScript上のFFIしている証は、foreignキーワードしかありません。

foreign import cumulativeSums :: Array Int -> Array Int

export const cumulativeSums = arr => {
  let sum = 0
  let sums = []
  arr.forEach(x => {
    sum += x;
    sums.push(sum);
  });
  return sums;
};

ライブラリ開発者はともかく、通常の開発者はこれに気づくことは困難です。

開発コード

import Effect.Console (log)

main :: Effect Unit
main = do
  log "🍝"

ライブラリ内部

-- | Write a message to the console.
foreign import log
  :: String
  -> Effect Unit

コーディングスタイルが安定していない

このつぶやきのケースなどです。人それぞれコーディングスタイルが分かれます。ならわかりますが、ひとりの人があまりお作法を気にせずにパッケージのaliasをつけている気がします。せめて、命名規則が統一されていると嬉しいですね・・・。

https://twitter.com/ababupdownba/status/1588099285190860802?s=20&t=o1nYX5V7WTjKpvROUjdO-w

素晴らしいなと思った点

先に気になった部分を上げたので、後半は素晴らしいと思った点をあげます。やっぱり素晴らしい!魅力的だなーと思う点が確実にあります。

REPLが高機能

これは、PureScriptレベルの言語では当たり前かもしれませんが、typeやkindが見れます。また、pasteで複数行記述が楽なのは良いですね。特に初心者のうちは関数がどういった挙動をするのか確かめるのに重宝すると思います。

柔軟性の高さ

この点に全てが集約されていると言っても過言ではありません。パッケージの抽象度がとにかくとんでもなく高く、言語の拡張性が高いため、やりたいと思ったことはなんでもできるような気がします(語彙力と言語化できるだけの知識量がなくすみません・・・)

また、Elmと比較するとElmは基本的にフロントエンドにフォーカスした言語(なんとかバックエンドで動かす方法やLamderaのような試みは増えていますが)ですが、JavaScriptのFFIとの性質も相まって、バックエンドで動かすことができるためできることは無限です。

この2つの性質を考えると、一口にPureScriptをやると言っても十人十色の成果物ができると思っています。なので人口が増えていろんな人のいろんな成果物を眺めたいなーと思っています。

パッケージがとにかく豊富

気になる点のどのパッケージが必須なのかがわからないと相反するメリットですが、とにかく抽象度が高く細かーくパッケージ分割されています。(おそらく)数学由来の考え方が色濃く言語に反映されています。そのため、数学に詳しい人などの話とリンクすることが多く、基礎的なパッケージを1つ追うだけでも1日の暇が潰せて教養が高まります。基礎を身につければ応用の幅も大きく広がると思うので、長い目で身につけれれば良いなと感じます。

コミュニティがこれから発展していきそう

ゆきくらげさんがdiscordでPureScript-JPを立ち上げてくださいました! やはり言語コミュニティは人です。人から得られる知識の量と深さは、膨大なため、是非発展していって欲しいと思います。PureScriptを学んでみたい、教えたいと思っている人は是非ご参加ください!

https://zenn.dev/yukikurage/articles/482a8647421fd5

まとめ

まだまだPureScriptを触って日が浅く、言及が少なくてすみません。ただパッと見ただけでも、学ぶメリットが多い言語だと思いますし、人が増えて改善されていく面も多く残されていると思います。少しでもこの記事を見て興味を持ってくださってPureScriptの世界に飛び込んでくれる人が増えると良いなと思っています。

Discussion