雑記帳
初めての PureScript

初めて PureScript に触れてみた。

イメージ
前々から少し気になっていた PureScript にこの度触れてみた。
契機は
  • JavaScript を直接書きたくない。
というシンプルなもので、選択肢としては
などがあったのだけど、一番魅力的に映ったのがこの PureScript さん。
まずは初めてで、開発環境すらないという状況から始まるということで
に書かれている説明に則って、環境整備を始めるところから。
Agda の環境整備にはなかなか苦戦させられたけれど、PureScript の開発環境の整備は思いのほかサクサクできて、必要なコマンドが使用できる状態にまでは順調に持っていくことができた。
そして開発環境の整備が一通り済んでしまえば、以下のコマンドを実行することで PureScript プログラムの骨組みをカレントディレクトリに生成できるようになるらしい。
> spago init
実際に実行してみる...
C:\Users\hikaru\Desktop\PureScript>spago init
[info] Initializing a sample project or migrating an existing one..
[info] Updating package-set tag to "psc-0.15.7-20230408"
Fetching the new one and generating hashes.. (this might take some time)
[info] Generating new hashes for the package set file so it will be cached.. (this might take some time)
[info] Set up a local Spago project.
[info] Try running `spago build
おお、ちゃんと動いた。
この初期化によって自動生成された Main.purs の中身を覗いてみたところ、「一つの絵文字を出力するプログラム」になっていたので、その絵文字を「Hello World!」に置き換えてから、JavaScript へとトランスパイル (transpile) してみることにした。
↓ その出力文字列を書き換えたコードはこんな感じ。
module Main where

import Prelude

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

main :: Effect Unit
main = do
  log "Hello World!"
雰囲気めっちゃ Haskell じゃん!(そんで公式にも Haskell の影響を強く受けていると書いてある)
コードを普通にビルドする場合は、初期化時のメッセージ内にもある
> spago build
を実行するらしいのだけど、実際にブラウザが実行するクライアントサイドスクリプトとしてのコンパクトな JavaScript を生成したい場合は
> spago bundle-app
というコマンドの方を実行すればよいとのこと。
ではいざ実践。
(以下は再度やり直して得た出力なので、初回実行時の出力は少し異なったものになるかもしれない。)
C:\Users\hikaru\Desktop\PureScript>spago bundle-app
[info] Installing 3 dependencies.
[info] Searching for packages cache metadata..
[info] Recent packages cache metadata found, using it..
[info] Installing "console"
[info] Installing "prelude"
[info] Installing "effect"
[info] Installation complete.
[ 1 of 58] Compiling Type.Proxy
[ 2 of 58] Compiling Record.Unsafe
[ 3 of 58] Compiling Data.Void
[ 4 of 58] Compiling Data.Unit
[ 5 of 58] Compiling Data.NaturalTransformation
[ 6 of 58] Compiling Data.Boolean
[ 7 of 58] Compiling Control.Semigroupoid
[ 9 of 58] Compiling Control.Category
[ 8 of 58] Compiling Data.Symbol
[10 of 58] Compiling Data.Semiring
[11 of 58] Compiling Data.HeytingAlgebra
[12 of 58] Compiling Data.Semigroup
[13 of 58] Compiling Data.Show
[14 of 58] Compiling Data.Ring
[15 of 58] Compiling Data.Generic.Rep
[16 of 58] Compiling Data.BooleanAlgebra
[17 of 58] Compiling Data.Eq
[18 of 58] Compiling Data.CommutativeRing
[19 of 58] Compiling Data.EuclideanRing
[20 of 58] Compiling Data.Ordering
[21 of 58] Compiling Data.Ord
[22 of 58] Compiling Data.DivisionRing
[23 of 58] Compiling Data.Field
[25 of 58] Compiling Data.Bounded
[27 of 58] Compiling Data.Monoid
[26 of 58] Compiling Data.Reflectable
[24 of 58] Compiling Data.Function
[28 of 58] Compiling Data.Functor
[29 of 58] Compiling Control.Apply
[30 of 58] Compiling Data.Monoid.Generic
[31 of 58] Compiling Data.Bounded.Generic
[32 of 58] Compiling Control.Applicative
[33 of 58] Compiling Control.Bind
[34 of 58] Compiling Control.Monad
[35 of 58] Compiling Prelude
[36 of 58] Compiling Data.Monoid.Dual
[37 of 58] Compiling Data.HeytingAlgebra.Generic
[39 of 58] Compiling Data.Semigroup.First
[38 of 58] Compiling Data.Semiring.Generic
[40 of 58] Compiling Data.Eq.Generic
[41 of 58] Compiling Effect
[42 of 58] Compiling Data.Monoid.Multiplicative
[43 of 58] Compiling Data.Monoid.Disj
[44 of 58] Compiling Data.Monoid.Conj
[45 of 58] Compiling Data.Monoid.Endo
[46 of 58] Compiling Data.Semigroup.Last
[47 of 58] Compiling Data.Ord.Generic
[49 of 58] Compiling Data.Monoid.Additive
[51 of 58] Compiling Data.Semigroup.Generic
[48 of 58] Compiling Data.Show.Generic
[50 of 58] Compiling Data.Ring.Generic
[52 of 58] Compiling Effect.Class
[53 of 58] Compiling Effect.Unsafe
[54 of 58] Compiling Effect.Uncurried
[55 of 58] Compiling Effect.Console
[57 of 58] Compiling Main
[56 of 58] Compiling Effect.Class.Console
[58 of 58] Compiling Test.Main
[info] Build succeeded.

  index.js  238b

Done in 8ms
[info] Bundle succeeded and output file to index.js
上手くいったっぽい。
確認してみたところ、以下の JavaScript コードが出来上がってた!
(() => {
  // output/Effect.Console/foreign.js
  var log = function(s) {
    return function() {
      console.log(s);
    };
  };

  // output/Main/index.js
  var main = /* @__PURE__ */ log("Hello World!");

  // <stdin>
  main();
})();
すげー!!
JavaScript を書くのが億劫な僕としては Haskell と酷似した純粋関数型言語によって間接的に JavaScript を書けるというのは感動。
最近 GHC に Haskell コードを JavaScript コードへとトランスパイルする機能が追加された との情報を見たけれど、ここまで Haskell っぽいコーディングができるのであればこの PureScript で大満足だ!
取り敢えず、環境を整えられたということで、今後は公式が出しているチュートリアル
を追っかけてみることにする。(もしかしたらシリーズ化するかもしれない)