Nibbles とは
コードゴルフ言語の一種とのこと。GitHubはこちら。
面白そうなのでAtCoderで使用してみようと思って調べてみたところ日本語のインストール手順などがほとんど見つけられなかったため、いい機会だと思い記事執筆に至りました。
せっかくなので自分がハマった点も含めて実行したままの手順をほぼそのまま記載しています。
手元の環境でエラーにならない箇所などは適宜飛ばして読んでいただければと思います。
環境
Macです。
Apple M1 チップ
macOS Ventura 13.5
シェルはzsh
インストール手順
AtCoderで使用することを想定しているので、まずはAtCoder公式を見てみる。
AtCoderに記載の環境はUbuntuしかない。Ubuntu使用の場合は公式に記載されている手順実行するだけで良いのでは。
ただ私の環境はMacなので、Nibbles公式の方を確認する。
ただしどのバージョンをインストールすべきかをメモしておく。記事執筆時点では1.01。
このあとはNibbles公式のTry It を確認し、その手順に沿って進めていく。
Haskellのインストール
You will need GHC 8.0.2 - 8.10.7. I recommend using ghcup to get it.
ghcupを使用するのを推奨すると書かれている。
書いてあるコマンドをそのままコピペ。
$ curl --proto '=https' --tlsv1.2 -sSf https://get-ghcup.haskell.org | sh
Press ENTER to proceed or ctrl-c to abort.
Note that this script can be re-run at any given time.
最初に上記のような文言が出てくる。とりあえずEnterを押す。
その後いくつかクエスチョンが出てくる。
Detected zsh shell on your system...
Do you want ghcup to automatically add the required PATH variable to "/Users/[ユーザー名]/.zshrc"?
[P] Yes, prepend [A] Yes, append [N] No [?] Help (default is "P").
PATHを.zshrcに追記するかどうかを聞いているように見える。
雰囲気で [A]。
Do you want to install haskell-language-server (HLS)?
HLS is a language-server that provides IDE-like functionality
and can integrate with different editors, such as Vim, Emacs, VS Code, Atom, ...
Also see https://haskell-language-server.readthedocs.io/en/stable/
[Y] Yes [N] No [?] Help (default is "N").
HaskellのLanguage Server をインストールするかどうか。
入れておいて困ることはないだろうと思って[Y]。
Do you want to enable better integration of stack with GHCup?
This means that stack won't install its own GHC versions, but uses GHCup's.
For more information see:
https://docs.haskellstack.org/en/stable/yaml_configuration/#ghc-installation-customisation-experimental
If you want to keep stacks vanilla behavior, answer 'No'.
[Y] Yes [N] No [?] Help (default is "Y").
よくわからなかったのでとりあえずデフォルトの[Y]。
System requirements
Note: On OS X, in the course of running ghcup you will be given a dialog box to install the command line tools. Accept and the requirements will be installed for you. You will then ne
ed to run the command again.
On Darwin M1 you might also need a working llvm installed (e.g. via brew) and have the toolchain exposed in PATH.
Press ENTER to proceed or ctrl-c to abort.
Installation may take a while.
これが出たらEnter。
===============================================================================
OK! /Users/[ユーザー名]/.zshrc has been modified. Restart your terminal for the changes to take effect,
or type ". /Users/[ユーザー名]/.ghcup/env" to apply them in your current terminal session.
===============================================================================
All done!
To start a simple repl, run:
ghci
To start a new haskell project in the current directory, run:
cabal init --interactive
To install other GHC versions and tools, run:
ghcup tui
If you are new to Haskell, check out https://www.haskell.org/ghcup/steps/
これが出たら完了。
あとは最後の方に書いてあるコマンドをターミナルにコピペして実行する。
$ . /Users/[ユーザー名]/.ghcup/env
Nibbles のインストール
ここで先ほどメモしておいたバージョンをダウンロードしてtgzファイルを解凍する。
ダウンロードフォルダのまま作業を進めるのがなんとなく嫌だったので、解凍済みのフォルダをホームディレクトリへ移動した。
$ mv ~/Downloads/nibbles ~/.
インストール失敗(1回目)
公式の手順に沿ってコマンド実行。
$ ghc -O -package ghc *.hs
[ 1 of 23] Compiling Data.DList.Internal ( Data/DList/Internal.hs, Data/DList/Internal.o, Data/DList/Internal.dyn_o )
[ 2 of 23] Compiling Data.DList ( Data/DList.hs, Data/DList.o, Data/DList.dyn_o )
[ 3 of 23] Compiling Data.Digest.Murmur64 ( Data/Digest/Murmur64.hs, Data/Digest/Murmur64.o, Data/Digest/Murmur64.dyn_o )
[ 4 of 23] Compiling Data.Function.Memoize.Class ( Data/Function/Memoize/Class.hs, Data/Function/Memoize/Class.o, Data/Function/Memoize/Class.dyn_o )
[ 5 of 23] Compiling Data.Function.Memoize.TH ( Data/Function/Memoize/TH.hs, Data/Function/Memoize/TH.o, Data/Function/Memoize/TH.dyn_o )
[ 6 of 23] Compiling Data.Function.Memoize ( Data/Function/Memoize.hs, Data/Function/Memoize.o, Data/Function/Memoize.dyn_o )
Data/Function/Memoize.hs:176:16: error:
• No instance for (Memoizable [Int])
arising from a use of ‘memoize’
• In the first argument of ‘(.)’, namely
‘memoize (f . fromIntBase)’
In the expression: memoize (f . fromIntBase) . toIntBase
In an equation for ‘memoize’:
memoize f = memoize (f . fromIntBase) . toIntBase
|
176 | memoize f = memoize (f . fromIntBase) . toIntBase
| ^^^^^^^
[ 7 of 23] Compiling Data.List.Split.Internals ( Data/List/Split/Internals.hs, Data/List/Split/Internals.o, Data/List/Split/Internals.dyn_o )
[ 8 of 23] Compiling Data.List.Split ( Data/List/Split.hs, Data/List/Split.o, Data/List/Split.dyn_o )
[ 9 of 23] Compiling FileQuoter ( FileQuoter.hs, FileQuoter.o, FileQuoter.dyn_o )
[11 of 23] Compiling Hs ( Hs.hs, Hs.o, Hs.dyn_o )
[12 of 23] Compiling SmartList ( SmartList.hs, SmartList.o, SmartList.dyn_o )
[13 of 23] Compiling Types ( Types.hs, Types.o, Types.dyn_o )
[14 of 23] Compiling Polylib ( Polylib.hs, Polylib.o, Polylib.dyn_o )
[15 of 23] Compiling Expr ( Expr.hs, Expr.o, Expr.dyn_o )
Expr.hs:3:1: error:
Could not find module ‘State’
Use -v (or `:set -v` in ghci) to see a list of the files searched for.
|
3 | import State
| ^^^^^^^^^^^^
明らかにエラーが発生している。
手順を再度確認していると、こんなものが目に入った。
You will need GHC 8.0.2 - 8.10.7.
GHCのバージョンを確認してみる。
$ ghc --version
The Glorious Glasgow Haskell Compilation System, version 9.4.8
なるほど。じゃあ8.10.7を入れよう。
GHCのバージョンを変える
$ ghcup install ghc 8.10.7
8.0.2 - 8.10.7ならどれでもいいと思われるが、とりあえずその中で最新のものを入れた。
[ Info ] GHC installation successful
こんなのが表示されたら完了。
このままだとまだバージョンが変わっていないので、変更する。
$ ghcup set ghc 8.10.7
[ Info ] GHC 8.10.7 successfully set as default version
こんなのが表示されたら完了。
バージョンを確認する。
$ ghc --version
The Glorious Glasgow Haskell Compilation System, version 8.10.7
よし、これでインストールできるはずだ。
インストール失敗(2回目)
さっきと同じように公式の手順に沿って作業。
$ ghc -O -package ghc *.hs
<no location info>: error:
Warning: Couldn't figure out LLVM version!
Make sure you have installed LLVM between [9 and 13)
<no location info>: error:
Warning: Couldn't figure out LLVM version!
Make sure you have installed LLVM between [9 and 13)
<no location info>: error:
Warning: Couldn't figure out LLVM version!
Make sure you have installed LLVM between [9 and 13)
<no location info>: error:
Warning: Couldn't figure out LLVM version!
Make sure you have installed LLVM between [9 and 13)
[ 1 of 22] Compiling Data.DList.Internal ( Data/DList/Internal.hs, Data/DList/Internal.o, Data/DList/Internal.dyn_o )
<no location info>: error:
Warning: Couldn't figure out LLVM version!
Make sure you have installed LLVM between [9 and 13)
ghc: could not execute: opt
明らかにエラーが発生している。
Warning: Couldn't figure out LLVM version!
で検索するとこのようなissueが出てきた。
このissue起票者のコメントに以下のようなものがあった。
For that I had to do a
brew install llvm@12
and added/opt/homebrew/opt/llvm@12/bin
toPATH
(in.zshrc
)
なるほど。これを読んで思ったのだが、私はそもそもllvmをインストールしていないような気がする。もしかしたらすでに入っているかもしれないが、とりあえずインストールしてみる。
$ brew install llvm@12
して
$ echo 'export PATH="/opt/homebrew/opt/llvm@12/bin:$PATH"' >> ~/.zshrc
して
$ source ~/.zshrc
これでどうですかね。
$ ghc -O -package ghc *.hs
<no location info>: error:
Warning: Couldn't figure out LLVM version!
Make sure you have installed LLVM between [9 and 13)
<no location info>: error:
Warning: Couldn't figure out LLVM version!
Make sure you have installed LLVM between [9 and 13)
<no location info>: error:
Warning: Couldn't figure out LLVM version!
Make sure you have installed LLVM between [9 and 13)
<no location info>: error:
Warning: Couldn't figure out LLVM version!
Make sure you have installed LLVM between [9 and 13)
[ 1 of 22] Compiling Data.DList.Internal ( Data/DList/Internal.hs, Data/DList/Internal.o, Data/DList/Internal.dyn_o )
<no location info>: error:
Warning: Couldn't figure out LLVM version!
Make sure you have installed LLVM between [9 and 13)
ghc: could not execute: opt
変わらないじゃん!
さっきのissueではみんなパスのことを話していた。
.zshrc
を見てみる。
... 中略 ...
[ -f "/Users/[ユーザー名]/.ghcup/env" ] && . "/Users/[ユーザー名]/.ghcup/env" # ghcup-envexport PATH="/opt/homebrew/opt/llvm@12/bin:$PATH"
おかしなことが起きていた。
... 中略 ...
[ -f "/Users/[ユーザー名]/.ghcup/env" ] && . "/Users/[ユーザー名]/.ghcup/env" # ghcup-env
export PATH="/opt/homebrew/opt/llvm@12/bin:$PATH"
これで保存して再度source ~/.zshrc
する
$ source ~/.zshrc
インストール成功
$ ghc -O -package ghc *.hs
[ 1 of 22] Compiling Data.DList.Internal ( Data/DList/Internal.hs, Data/DList/Internal.o, Data/DList/Internal.dyn_o )
[ 2 of 22] Compiling Data.DList ( Data/DList.hs, Data/DList.o, Data/DList.dyn_o )
[ 3 of 22] Compiling Data.Digest.Murmur64 ( Data/Digest/Murmur64.hs, Data/Digest/Murmur64.o, Data/Digest/Murmur64.dyn_o )
[ 4 of 22] Compiling Data.Function.Memoize.Class ( Data/Function/Memoize/Class.hs, Data/Function/Memoize/Class.o, Data/Function/Memoize/Class.dyn_o )
[ 5 of 22] Compiling Data.Function.Memoize.TH ( Data/Function/Memoize/TH.hs, Data/Function/Memoize/TH.o, Data/Function/Memoize/TH.dyn_o )
[ 6 of 22] Compiling Data.Function.Memoize ( Data/Function/Memoize.hs, Data/Function/Memoize.o, Data/Function/Memoize.dyn_o )
[ 7 of 22] Compiling Data.List.Split.Internals ( Data/List/Split/Internals.hs, Data/List/Split/Internals.o, Data/List/Split/Internals.dyn_o )
[ 8 of 22] Compiling Data.List.Split ( Data/List/Split.hs, Data/List/Split.o, Data/List/Split.dyn_o )
[ 9 of 22] Compiling FileQuoter ( FileQuoter.hs, FileQuoter.o, FileQuoter.dyn_o )
[10 of 22] Compiling Header ( Header.hs, Header.o, Header.dyn_o )
[11 of 22] Compiling Hs ( Hs.hs, Hs.o, Hs.dyn_o )
[12 of 22] Compiling SmartList ( SmartList.hs, SmartList.o, SmartList.dyn_o )
[13 of 22] Compiling Types ( Types.hs, Types.o, Types.dyn_o )
[14 of 22] Compiling Polylib ( Polylib.hs, Polylib.o, Polylib.dyn_o )
[15 of 22] Compiling Expr ( Expr.hs, Expr.o, Expr.dyn_o )
[16 of 22] Compiling Parse ( Parse.hs, Parse.o, Parse.dyn_o )
[17 of 22] Compiling ParseArgs ( ParseArgs.hs, ParseArgs.o, ParseArgs.dyn_o )
[18 of 22] Compiling OpsHelper ( OpsHelper.hs, OpsHelper.o, OpsHelper.dyn_o )
[19 of 22] Compiling Args ( Args.hs, Args.o, Args.dyn_o )
[20 of 22] Compiling Ops ( Ops.hs, Ops.o, Ops.dyn_o )
[21 of 22] Compiling Compile ( Compile.hs, Compile.o, Compile.dyn_o )
[22 of 22] Compiling Main ( nibbles.hs, nibbles.o, nibbles.dyn_o )
Linking nibbles ...
できたっぽい。
公式にはこの後にこのように書いてある。
This creates the
nibbles
binary. You will need to run nibbles code from this directory unless you install the libraries below.
次に書いてるライブラリをインストールすれば、このディレクトリ以外でも実行できるよということか。
ライブラリのインストール
書いてある通り実行した。
$ rm -r Data
$ cabal install --lib dlist split murmur-hash memoize
Resolving dependencies...
Build profile: -w ghc-8.10.7 -O1
In order, the following will be built (use -v for more details):
- dlist-1.0 (lib) (requires download & build)
- memoize-1.1.2 (lib) (requires download & build)
- murmur-hash-0.1.0.10 (lib) (requires download & build)
- split-0.2.5 (lib) (requires download & build)
Downloading split-0.2.5
Downloaded split-0.2.5
Downloading murmur-hash-0.1.0.10
Starting split-0.2.5 (lib)
Downloaded murmur-hash-0.1.0.10
Downloading dlist-1.0
Starting murmur-hash-0.1.0.10 (lib)
Downloaded dlist-1.0
Downloading memoize-1.1.2
Starting dlist-1.0 (lib)
Building split-0.2.5 (lib)
Building murmur-hash-0.1.0.10 (lib)
Building dlist-1.0 (lib)
Downloaded memoize-1.1.2
Starting memoize-1.1.2 (lib)
Installing murmur-hash-0.1.0.10 (lib)
Completed murmur-hash-0.1.0.10 (lib)
Building memoize-1.1.2 (lib)
Installing split-0.2.5 (lib)
Completed split-0.2.5 (lib)
Installing dlist-1.0 (lib)
Completed dlist-1.0 (lib)
Installing memoize-1.1.2 (lib)
Completed memoize-1.1.2 (lib)
うまくいったっぽい。
プログラム実行
nibblesディレクトリを見ていたところ、testディレクトリの中にintegration_test.nbl
というファイルを発見した。
手始めにこれを実行してみることにした。
$ nibbles integration_test.nbl
zsh: command not found: nibbles
そうですか。。。
.zshrcに追記
なんとなく原因の想像がついたので.zshrc
に以下を追記
export PATH="/Users/[ユーザー名]/nibbles:$PATH"
source ~/.zshrc
する。
$ source ~/.zshrc
再度実行
$ nibbles integration_test.nbl
size = 17 nibbles (8.5 bytes)
out.hs:13:1: error:
Could not load module ‘Data.Set’
It is a member of the hidden package ‘containers-0.6.5.1’.
You can run ‘:set -package containers’ to expose it.
(Note: this unloads all the modules in the current scope.)
Use -v (or `:set -v` in ghci) to see a list of the files searched for.
|
13 | import qualified Data.Set as Set
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
out.hs:19:1: error:
Could not load module ‘Data.ByteString’
It is a member of the hidden package ‘bytestring-0.10.12.0’.
You can run ‘:set -package bytestring’ to expose it.
(Note: this unloads all the modules in the current scope.)
Use -v (or `:set -v` in ghci) to see a list of the files searched for.
|
19 | import qualified Data.ByteString as B8
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
nibbles: failed to compile hs (likely an internal nibbles bug, please report it!)
CallStack (from HasCallStack):
error, called at nibbles.hs:163:24 in main:Main
moduleが無いらしい。
不足しているライブラリをインストール
バージョン指定してインストールする。
$ cabal install --lib containers-0.6.5.1
Resolving dependencies...
$ cabal install --lib bytestring-0.10.12.0
Resolving dependencies...
実行成功
再度実行してみる。
$ nibbles integration_test.nbl
size = 17 nibbles (8.5 bytes)
a♯b
おお、うまくいってるっぽいぞ!
nibblesディレクトリ以外で実行
この工程を踏んでいるので、nibblesディレクトリ以外でも実行できるはず。
ホームディレクトリにnibbles_test
ディレクトリを作成して、intro.nbl
ファイルを作成する。
$ cd ~
$ mkdir nibbles_test
$ cd nibbles_test
$ touch intro.nbl
intro.nbl
の中身はチュートリアルの最初の内容で以下の通りにした。
+2 1
実行
$ nibbles intro.nbl
size = 5 nibbles (2.5 bytes)
3
チュートリアルと見比べてみる。
size = 5 nibbles (3 bytes)
3
なんか少し違う。。。けどこんなことが書いてあった。
A file appears named intro.nbb (nbb is the file extension for binary Nibbles programs) which has a size of 3 bytes. That compactification was not as good as the promised divide by 2... but it would have been 2.5 bytes if we were measuring that way (and small numbers are a bad example). FYI you can automatically expand .nbb files back to literate form using -e.
許されたことにしておく。
ひとまず環境構築は完了。
終わりに
最初のプログラムが実行できるようになるまでに結構手こずった。
この後は構文など試してみてみる&AtCoderの問題を解いてみようと思う。