概要
Unison という開発中のプログラミング言語を触ってみました。
おそらく日本で最初の Unison の記事です。
"3-clause BSD" LICENSE のもとに配布されています。
言語の特徴
- 静的型付き純粋関数型
- モダンで Haskell に似た文法を持つ
- 分散システムでも1つのプログラムで動かせる
環境構築
Unison の開発環境を構築します。
- Haskell Stack のインストール
- リポジトリの取得
git clone --recursive https://github.com/unisonweb/unison.git
- ビルド&テスト
stack build && stack exec tests
- 初期設定
stack exec unison init
- 起動1
stack exec unison
- ".base" ライブラリの取得
起動したインタラクティブシェルで以下のコマンドを実行します。
.> pull https://github.com/unisonweb/base .base
エラーが出なければ環境構築は終了です。
Hello World
unison を起動したディレクトリに scratch.u
というファイルを作成します。
デフォルトではこのファイルが自動的に watch されます。
scratch.u
をテキストエディタで開いて以下のコードを入力します。
hello : '{IO} ()
hello = '(base.io.printLine "Hello world!")
ファイルを保存すると repl が実行されます。
.>
I found and typechecked these definitions in
~/projects/unison/scratch.u. If you do an `add` or `update`,
here's how your codebase would change:
⍟ These new definitions are ok to `add`:
hello : '{IO} ()
Now evaluating any watch expressions (lines starting with
`>`)... Ctrl+C cancels.
インタラクティブシェルでコマンドを実行してみましょう。
.> run hello
Hello world!
.>
おめでとうございます。これであなたも unison を完全に理解できましたね!
Namespace
利便性のために namespace を分けてみましょう。
新しい namespace を作成して、そこに hello 関数を移動します。
.>
で始まる行は unison インタラクティブシェルで実行します。
注意: .>
や .mylibrary>
は入力しません。
- namespace の作成
.> namespace mylibrary
- namespace の移動
.> cd .mylibrary
.mylibrary>
- 関数の移動
.mylibrary> move.term .hello hello
- namespace の探索
.mylibrary> find
1. hello : '{IO} ()
が表示されれば "mylibrary" namespace に hello を移動できたことになります。
Publish
コードを GitHub repository に namespace を publish してみましょう。
- Github Repository の作成
Github に repository を作成します。
仮に "myunisonrepo" という名前とします。 - namespace の移動
.mylibrary> cd .
- release namespace の複製
.> copy.namespace mylibrary mylibrary.releases.v1
- 動作確認
.> cd mylibrary.releases.v1
.mylibrary.releases.v1> find
- publish
cd .mylibrary
push git@github.com:<yourgithubuser>/myunisonrepo
エラーが出なければ成功です。
push に失敗した場合には github の認証を確認してください。
下記のような構成が repository に作られます。
FizzBuzz
Unison で FizzBuzz を書いてみましょう。
use .base
fizzBuzz : Nat -> Text
fizzBuzz n =
case (mod n 3, mod n 5) of
(x,y) | (x == 0) && (y == 0) -> "FizzBuzz"
(x,_) | (x == 0) -> "Fizz"
(_,y) | (y == 0) -> "Buzz"
_ -> toText n
> map fizzBuzz (range 1 101)
Nat
は自然数、Text
は文字列の型です。
fizzBuzz : Nat -> Text
は自然数を引数に取り文字列を返す関数 fizzBuzz
を表しています。
range 1 101
は1から100までの自然数の List です。
map 関数に fizzBuzz をつけて自然数の List に適用すると以下の出力が得られます。
[ "1",
"2",
"Fizz",
"4",
"Buzz",
"Fizz",
"7",
"8",
"Fizz",
"Buzz",
"11",
"Fizz",
"13",
"14",
"FizzBuzz",
"16",
"17",
"Fizz",
"19",
"Buzz",
...(以下略)
気になったこと
- Haskell が書ける人には書きやすい。
- ファイルモジュールではなくて namespace 単位で分別するなどの独特の思想が面白い。
- publish した repository 内のバイナリファイルに可読性がないのでドキュメントが必須。
注意
- Unison は開発中の言語なので仕様が大きく変わる可能性があります。執筆時点の最新バージョンを使いました。
- 情報が少なく仕様歴も浅いので仕様を完全には把握していません。間違っている記述を発見したらご指摘いただけると助かります。
-
起動まで成功するとインタラクティブシェルが立ち上がります。 ↩