🐙

HaskellでAtCoderを楽しむためのstack-template(2025-10-14改訂版)

に公開

はじめに

この記事は、AtCoderをHaskellで楽しむために筆者が作成したstackのテンプレートの使い方を説明します。さらに、このテンプレートもとに、カスタマイズしやすいように、筆者のテンプレートファイルatcoder.hsfilesの概要を解説します。

AtCoder 言語アップデート 2025 に対応できるように設定しますが、検証が不十分である点はご理解ください。

おことわり

この記事を、読んで、あるいは、読まずに、おこなわれた全ての行為について、筆者は一切の責任を負いません。筆者の手順、テンプレートの利用は、自己責任でおこなって下さい

前提となるPC環境

デバイス基本仕様

項目 内容
CPU 12th Gen Intel(R) Core(TM) i9-12900H
GPU NVIDIA RTX A2000 8GB
RAM 64GB
OS Pop!_OS 24.04 LTS Beta

Pop!_OS 24.04 LTS Beta は Ubuntu 24.04 LTS をベースにした Linux ディストリビューション

前提PC環境とその構築概要

開発用基本パッケージ

Haskellの言語処理系GHCの前提となる基本パッケージのインストール

sudo apt install build-essential libffi-dev libgmp-dev libncurses-dev
sudo apt install libgsl-dev liblapack-dev libatlas-base-dev

Haskell処理系

  • GHCup 0.1.50.2
    • Stack 3.7.1
    • HLS 2.10.0.0
    • cabal 3.16.0.0
    • GHC 9.8.4

GHCupのサイトからダウンロード、セットアップ

curl --proto '=https' --tlsv1.2 -sSf https://get-ghcup.haskell.org | sh

とすると、


Welcome to Haskell!

This script can download and install the following binaries:
  * ghcup - The Haskell toolchain installer
  * ghc   - The Glasgow Haskell Compiler
  * cabal - The Cabal build tool for managing Haskell software
  * stack - A cross-platform program for developing Haskell projects (similar to cabal)
  * hls   - (optional) A language server for developers to integrate with their editor/IDE

ghcup installs only into the following directory,
which can be removed anytime:
  /home/nobsun/.ghcup

Press ENTER to proceed or ctrl-c to abort.
Note that this script can be re-run at any given time.

ここで ENTERキーを押す。


  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100 29.6M  100 29.6M    0     0  15.4M      0  0:00:01  0:00:01 --:--:-- 15.4M
[ Info  ] downloading: https://raw.githubusercontent.com/haskell/ghcup-metadata/master/ghcup-0.0.9.yaml as file /home/nobsun/.ghcup/cache/ghcup-0.0.9.yaml
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100  560k  100  560k    0     0  6831k      0 --:--:-- --:--:-- --:--:-- 6916k
[ Info  ] Upgrading GHCup...
[ Warn  ] No GHCup update available

System requirements
  Note: You need the following packages: curl g++ gcc gmp make ncurses realpath xz-utils pkg-config. Consult your distro documentation on the exact names of those packages.

Press ENTER to proceed or ctrl-c to abort.

ここも、ENTERキーを押します。


-------------------------------------------------------------------------------

GHCup provides different binary distribution "channels". These are collections of tools
and may differ in purpose and philosophy. First, we select the base channel.

[S] Skip  [D] Default (GHCup maintained)  [V] Vanilla (Upstream maintained)  [?] Help (default is "Skip").

ここは、デフォルトで Skip、単にENTERキーを押します。


-------------------------------------------------------------------------------

Detected bash shell on your system...
Do you want ghcup to automatically add the required PATH variable to "/home/nobsun/.bashrc"?

[P] Yes, prepend  [A] Yes, append  [N] No  [?] Help (default is "P").

パス設定を~/.bashrc に追加。
これも、デフォルトで prepend、単にENTERキーを押します。


-------------------------------------------------------------------------------
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").

Y

HLS とエディタを連携させるか。筆者は VS Code を使っているので 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/configure/customisation_scripts/#ghc-installation-customisation
If you want to keep stacks vanilla behavior, answer 'No'.

[Y] Yes  [N] No  [?] Help (default is "Y").

stack と GHCup を連携するか。デフォルトの Yes、単に ENTERキーを押します。
あとは、最後まで待ちます。少し時間がかかる場合があります。


[ Info  ] downloading: https://downloads.haskell.org/ghcup/unofficial-bindists/ghc/9.6.7/ghc-9.6.7-x86_64-rocky8-linux.tar.xz as file /home/nobsun/.ghcup/cache/ghc-9.6.7-x86_64-rocky8-linux.tar.xz
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100  192M  100  192M    0     0  26.4M      0  0:00:07  0:00:07 --:--:-- 28.1M
[ Info  ] verifying digest of: ghc-9.6.7-x86_64-rocky8-linux.tar.xz
[ Info  ] Unpacking: ghc-9.6.7-x86_64-rocky8-linux.tar.xz to /home/nobsun/.ghcup/tmp/ghcup-7c47c5fdf6996df2
[ Info  ] Installing GHC (this may take a while)
[ ghc-make ] fi
[ ghc-make ] Copying docs to /home/nobsun/.ghcup/tmp/ghcup-bdeec55a8c07d3c0/home/nobsun/.ghcup/ghc/9.6.7/share/doc/ghc-9.6.7
[ ghc-make ] /usr/bin/install -c -m 755 -d "/home/nobsun/.ghcup/tmp/ghcup-bdeec55a8c07d3c0/home/nobsun/.ghcup/ghc/9.6.7/share/doc/ghc-9.6.7"
[ ghc-make ] if [ -d doc ]; then \
[ ghc-make ] 	cd doc; /usr/bin/find . -type f -exec sh -c \
[ ghc-make ] 		'/usr/bin/install -c -m 755 -d "/home/nobsun/.ghcup/tmp/ghcup-bdeec55a8c07d3c0/home/nobsun/.ghcup/ghc/9.6.7/share/doc/ghc-9.6.7/`dirname $1`" && /usr/bin/install -c -m 644 "$1" "/home/nobsun/.ghcup/tmp/ghcup..[ Info  ] Merging file tree from "/home/nobsun/.ghcup/tmp/ghcup-bdeec55a8c07d3c0/home/nobsun/.ghcup/ghc/9.6.7" to "/home/nobsun/.ghcup/ghc/9.6.7"
[ Info  ] GHC installation successful
[ Info  ] HLS is not supported for 9.6.7 yet. To build from source, run:
[ ...   ]   ghcup compile hls -g 2.9.0.1 --ghc 9.6.7 --cabal-update -- --constraint="ghc-lib-parser == 9.8.5.20250214" --index-state="2025-02-14T12:50:38Z"
[ Info  ] GHC 9.6.7 successfully set as default version
[ Info  ] downloading: https://downloads.haskell.org/~ghcup/unofficial-bindists/cabal/3.12.1.0/cabal-install-3.12.1.0-x86_64-linux-centos7.tar.xz as file /home/nobsun/.ghcup/cache/cabal-install-3.12.1.0-x86_64-linux-centos7.tar.xz
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100 6962k  100 6962k    0     0  9521k      0 --:--:-- --:--:-- --:--:-- 9511k
[ Info  ] verifying digest of: cabal-install-3.12.1.0-x86_64-linux-centos7.tar.xz
[ Info  ] Unpacking: cabal-install-3.12.1.0-x86_64-linux-centos7.tar.xz to /home/nobsun/.ghcup/tmp/ghcup-5ff794354b9df118
[ Info  ] Installing cabal
[ Info  ] Cabal installation successful
Downloading the latest package list from hackage.haskell.org
Package list of hackage.haskell.org has been updated.
The index-state is set to 2025-10-13T08:48:23Z.
To revert to previous state run:
    cabal v2-update 'hackage.haskell.org,2025-10-08T23:27:01Z'
[ Info  ] downloading: https://downloads.haskell.org/~ghcup/unofficial-bindists/haskell-language-server/2.10.0.0/haskell-language-server-2.10.0.0-x86_64-linux-rocky8.tar.xz as file /home/nobsun/.ghcup/cache/haskell-language-server-2.10.0.0-x86_64-linux-rocky8.tar.xz
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100  196M  100  196M    0     0  25.1M      0  0:00:07  0:00:07 --:--:-- 26.1M
[ Info  ] verifying digest of: haskell-language-server-2.10.0.0-x86_64-linux-rocky8.tar.xz
[ Info  ] Unpacking: haskell-language-server-2.10.0.0-x86_64-linux-rocky8.tar.xz to /home/nobsun/.ghcup/tmp/ghcup-0b7f1847d479e5c8
[ Info  ] Installing HLS
[ Info  ] Merging file tree from "/home/nobsun/.ghcup/tmp/ghcup-e004da959664b2f5/home/nobsun/.ghcup/hls/2.10.0.0" to "/home/nobsun/.ghcup/hls/2.10.0.0"
[ Info  ] HLS installation successful
[ Info  ] This is just the server part of your LSP configuration. Consult the README on how to
[ ...   ] configure HLS, your project and your LSP client in your editor:
[ ...   ]   https://haskell-language-server.readthedocs.io/en/stable/
[ Info  ] downloading: https://downloads.haskell.org/~ghcup/unofficial-bindists/stack/3.3.1/stack-3.3.1-linux-x86_64.tar.gz as file /home/nobsun/.ghcup/cache/stack-3.3.1-linux-x86_64.tar.gz
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100 21.3M  100 21.3M    0     0  24.4M      0 --:--:-- --:--:-- --:--:-- 24.4M
[ Info  ] verifying digest of: stack-3.3.1-linux-x86_64.tar.gz
[ Info  ] Unpacking: stack-3.3.1-linux-x86_64.tar.gz to /home/nobsun/.ghcup/tmp/ghcup-932f0c9061d820f1
[ Info  ] Installing stack
[ Info  ] Stack installation successful
[ Info  ] Stack manages GHC versions internally by default. To improve integration, please visit:
[ ...   ]   https://www.haskell.org/ghcup/guide/#stack-integration
[ ...   ]
[ ...   ] Also check out:
[ ...   ]   https://docs.haskellstack.org/en/stable/yaml_configuration
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100   766  100   766    0     0   1319      0 --:--:-- --:--:-- --:--:--  1318

===============================================================================

OK! /home/nobsun/.bashrc has been modified. Restart your terminal for the changes to take effect,
or type ". /home/nobsun/.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/

これで端末を再起動すれば、設定が有効になる。

処理系のバージョン調整

GHCup を使って、

  • Stack および Cabal の最新バージョンをインストールし、デフォルトに設定
  • ghc 9.8.4 をインストールし、デフォルトに設定

します。

ghcup tui

矢印キー ↑ ↓ を使って選択、i キーを押すとインストールされる。その後、もういちど選択して、 s キーを押すとデフォルトに設定される。

AtCoder ツール

以下の

  • online-judge-tool
  • atcoder-cli
  • aclogin

online-judge-tool および atcoder-cli については以下の記事を参考にインストール、設定してください。

https://zenn.dev/ok_xmonad/articles/ae1c5bf0a955c1

現時点では、上の2つのツールだけでは、AtCoder へのログインに失敗します。以下のツールでセッションcoockieを保存するなどが必要です。

https://github.com/key-moon/aclogin/blob/main/README.md#aclogin

AtCoder用 stack-template の使い方

stack-templates リポジトリのフォーク

ここで紹介するテンプレートは、十分にテストされたものとはいえないのと、筆者の個人的嗜好が強い設定になっているので、自分用に修正、カスタマイズしたくなるところが多いでしょう。とくに、各ライブラリパッケージのバージョン調整、GHCのオプションや言語拡張プラグマ、および、雛形となるMain.hsなどは自分用にカスタマイズすることをお勧めします。

カスタマイズいろいろ試すには、

https://github.com/nobsun/stack-templates

を自分のGitHubアカウントにフォークしてください。カスタマイズするファイルは、atcoder.hsfiles です。
自分のカスタムatcoder.hsfilesを試すには、たとえば、

stack new abc426 <GitHubユーザー名>/atcoder

としてください。手元にAtCoderのプロジェクトabc426ディレクトリが新規に作成できます。

プロジェクトの流れ

例として、ABC 426 用のプロジェクトを作ります。
あらかじめ、

acc login

で、AtCoderへログインを確認しておきます。ログイン済の場合は「プロジェクトの初期化」にすすんでください。そうでない場合は、acc はログインを試みますが、失敗しますので、acloginでログインしてください。

aclogin

プロジェクトの初期化

stack new abc426 nobsun/atcoder ## `nobsun`の代りにフォーク先のGitHubユーザー名を使ってください
cd abc426
source activate ## ユーティリティスクリプトの実行権限 ON
./building      ## ライブラリパッケージの準備

次の initializing スクリプトは、当該コンテストのテスト用サンプルケースを取得しようとします。公開前のコンテストからは取ってこれませんので、initializing スクリプトは必ずAtCoderの当該コンテストが公開後(コンテストが開始後)に起動してください。

./initializing  ## プロジェクトディレクトリの(再)構成、テスト用サンプルデータの取得

注意

initializingスクリプトは内部でsettingスクリプトを呼んでいます。settingスクリプトは、implicit-hieパッケージが提供するgen-hieコマンドを使います。gen-hieがローカル環境にない場合は、implicit-hieパッケージを無断でインストールし、gen-hieコマンドを$HOME/.local/bin/に設置します。

問題 A を「現在の問題」に設定する

./resetting a

問題 A の解答プログラムを作成する

競技者は、app/a/Main.hs を編集して、問題 A の解答プログラムを作成してください。

問題 A の解答プログラムのビルドとサンプルデータによるテスト

./checking

問題 A の解答プログラムを提出 -- (未確認)

コンテスト開催時間中のみ以下コマンドで提出可能ならいいなぁ。

./submitting

提出できないときは、Web上で提出してください。

stack のテンプレートファイル

テンプレートファイルは、.hsfilesという拡張子をもつテキストファイルです。筆者はatcoder.hsfilesというファイルにしています。テンプレートは、stack new のときに、プロジェクトのルートディレクトリ以下に配置するファイルを指定するものです。

カスタムしたテンプレートは、GitHub にstack-templatesというリポジトリを作成してその中に置くと、ローカルマシンで、stack new で指定できようになります。複数あれば、状況に応じて使い分けられます。

たとえば、この記事のテンプレートは、https://github.com/nobsun/stack-templates/atcoder.hsfilesなので、これをそのまま使って、ABC 426を楽しむには、

stack new abc426 nobsun/atcoder

とします。

プロジェクトディレクトリの初期構成

stack new abc426 nobsun/atcoderを実行直後のプロジェクトディレクトリの構成は以下のようになります。

$ tree -a abc426
abc426
├── .ghci
├── .gitignore
├── ChangeLog.md
├── LICENSE
├── README.md
├── Setup.hs
├── abc426.cabal
├── activate
├── app
│   ├── Main.hs
│   └── zzz
│       └── add-entry
│           └── Main.hs
├── building
├── checking
├── executing
├── ghcing
├── initializing
├── package.yaml
├── resetting
├── setting
├── stack.yaml
└── submitting

4 directories, 20 files

これらのファイルのうち、abc426.cabalおよびstack.yaml以外のファイルは、atcoder.hsfilesで指定します。abc426.cabalは、stackがpackage.yamlをもとに生成してくれますので特にさわる必要はありません。stack.yamlは、stackがデフォルトで設定したものを、ユーティリティスクリプトintializingが書き換えます。

atcoder.hsfiles の構成

テンプレートファイル *.hsfilesは、複数のセクションから構成されて、個々のセクションはフラットに順不同でならべる。また、個々のセクションは、stack newコマンドでプロジェクトディレクトリに初期配置する個々のファイルに対応します。

個々のセクションは、START_FILEプラグマ指定行、すなわち、{-# START_FILE 《ファイルパス》 #-}のみからなる行から、次のSTART_FILEプラグマ指定行またはファイル終端の直前行までになります。

.ghci

テンプレートのapp/Main.hsにおける言語拡張プラグマと同じものをghciでも有効にしています。ユーティリティスクリプトghcingで必要になる。

{-# START_FILE .ghci #-}
:set -XCPP
:set -XGHC2021 -XLambdaCase -XMultiWayIf -XNPlusKPatterns -XOverloadedStrings -XLexicalNegation
:set -XDataKinds -XPolyKinds -XNoStarIsType -XTypeFamilyDependencies -XUndecidableInstances

.gitignore

プロジェクトをgitで管理する場合に必要になります。stackを使うことを前提としているので、.cabalファイルは管理外にしてあります。
{{name}}の部分は、stack newコマンド実行の際に、渡されたプロジェクト名に置換されます。

{-# START_FILE .gitignore #-}
.stack-work/
dist-new/
{{name}}.cabal
*.log
.curname
core
*.hi
*.o
*~

ChangeLog.md

{-# START_FILE ChangeLog.md #-}
# ChangeLog for {{name}}

## Unreleased changes

LICENSE

BSD-3の使用許諾書ファイル。{{copyright}}および{{author-name}}の部分は、stackの設定ファイル、デフォルトでは$HOME/.stack/config.yamlで設定されている、それぞれcopyrightおよびauthor-nameの値で置換されます。

{-# START_FILE LICENSE #-}
Copyright {{copyright}}

All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:

    * Redistributions of source code must retain the above copyright
      notice, this list of conditions and the following disclaimer.

    * Redistributions in binary form must reproduce the above
      copyright notice, this list of conditions and the following
      disclaimer in the documentation and/or other materials provided
      with the distribution.

    * Neither the name of {{author-name}}{{^author-name}}Author name here{{/author-na
me}} nor the names of other
      contributors may be used to endorse or promote products derived
      from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

README.md

{-# START_FILE README.md #-}
# {{name}}

Setup.hs

{-# START_FILE Setup.hs #-}
import Distribution.Simple
main = defaultMain

activate

もろもろのツール群をアクティベート

  • ユーティリティスクリプトを実行フラッグON
  • stack.yaml 書き換え
  • 利用パッケージ設定(初回は少々時間がかかります)
{-# START_FILE activate #-}
# 実行ビットON
chmod u+x building checking executing ghcing initializing resetting setting submitting

# stack.yaml 書き換え
tee stack.yaml > /dev/null << 'EOF'
snapshot: lts-23.28

packages:
- .
EOF

# 利用パッケージ調整
stack build

initializing

プロジェクトの初期化を行います。

  • 雛形Main.hsを atcoder-cli に設定
  • atcoder-cli の設定
  • atcoder-cli によるプロジェクト初期化(問題毎のディレクトリ生成、サンプルケースの取得、設置
  • stack 用にプロジェクト再編成
{-# START_FILE initializing #-}
#!/bin/bash

# 雛形`Main.hs`を atcoder-cli に設定
cp app/Main.hs ~/.config/atcoder-cli-nodejs/haskell/

# atcoder-cli の設定
acc config default-task-choice all
acc config default-template haskell

# atcoder-cli によるプロジェクト初期化
acc new {{name}}

# stack 用にプロジェクト再編成
mv {{name}}/contest.acc.json ./

jq -r '.tasks[].id' ./contest.acc.json | while read tid; do
  mv {{name}}/${tid: -1} app/
  ./setting ${tid: -1}
done

rmdir {{name}}
cp contest.acc.json app/
ln -s ./app ./abc426

./resetting a

setting

指定した問題ID(通常、aからgまでのどれか)用のサブプロジェクトディレクトリをapp/以下に初期化します。

{-# START_FILE setting #-}
#!/bin/bash

# 指定した問題用のエントリーを package.yaml に追加
stack exec -- add-entry $1

# 現在の問題を設定する
echo "export CURRENT_STACK_EXE_ENTRY=$1" > .curname

# 現在の問題用 Main.hs を仮ビルド
stack build {{name}}:exe:$1

# hie.yaml の更新
if type "gen-hie" > /dev/null 2>&1; then
  gen-hie > hie.yaml
else
  stack install implicit-hie
  gen-hie > hie.yaml
fi

resetting

「現在の問題」を指定した問題IDに再設定します。

{-# START_FILE resetting #-}
#!/bin/bash

echo "export CURRENT_STACK_EXE_ENTRY=$1" > .curname

checking

「現在の問題」に対応する解答プログラムをチェックします。

  • 解答プログラムのコンパイル
  • サンプル入力ごとに解答プログラムの実行し、出力をサンプル出力と比較
{-# START_FILE checking #-}
#!/bin/bash

source .curname

# 解答プログラムのコンパイル
./building

# 解答プログラムのテスト
oj t -c ./executing -d app/$CURRENT_STACK_EXE_ENTRY/tests

building

「現在の問題」に対応する解答プログラムをコンパイルする

{-# START_FILE building #-}
#!/bin/bash

source .curname
stack build {{name}}:exe:$CURRENT_STACK_EXE_ENTRY

executing

「現在の問題」に対応する解答プログラムを起動します。

{-# START_FILE executing #-}
#!/bin/bash

source .curname
stack exec -- $CURRENT_STACK_EXE_ENTRY

submitting

「現在の問題」に対応する解答プログラムを提出します。

{-# START_FILE submitting #-}
#!/bin/bash

source .curname

cd {{name}}/$CURRENT_STACK_EXE_ENTRY && acc s -s -- --no-open

ghcing

「現在の問題」に対する解答プログラムを GHCi にロードします。これは個別の関数の動作確認のために使用できます。

{-# START_FILE ghcing #-}
#!/bin/bash

source .curname
stack exec -- ghci app/$CURRENT_STACK_EXE_ENTRY/Main.hs

設定ファイルpackage.yaml

Stack 用のプロジェクト設定ファイル。ビルドの際にこのファイルをもとに、cabalファイルが自動生成されます。

default-extensionsの部分をカスタマイズした場合は、app/Main.hsの言語拡張プラグマ指定との整合性、および、.ghciのフラッグ設定との整合性に注意して調整してください。

ユーティリティHaskellスクリプトapp/zzz/Main.hs

指定した問題IDに対する解答プログラムのテンプレートを配置し、buildingexecutingでビルドおよび起動ができるように、package.yamlにエントリーを追加します。
このスクリプトはバグ修正以外では変更しないでください。

解答プログラムのテンプレート app/Main.hs

自分用にカスタマイズした解答プログラムの雛形は atcoder-cli の設定時に、$HOME/.config/atcoder-cli-nodejs/haskell/に置くことを想定しています。
したがって、通常このファイルが使われることはありません。カスタマイズの一例として参考になるかもしれません。

app/Main.hs の基本的な考え方

このファイルは一例にすぎませんので、完全に独自のものに差し替えてかまいません。完全に独自のものに差し替えるときは、このファイルでの言語拡張プラグマ指定と、package.yaml ファイルの default-extensions のリスト、および、.ghci ファイルでのフラッグ設定とが整合するようにしてください。

mainの定義は以下のとおりです。

main :: IO ()
main = B.interact (detokenize . encode . solve . decode . entokenize)

このパターンは、対話的(interactive)ではない問題にしか対応できません。しかし、AtCoder Beginner Contestでは対話的なプログラムが必要になることはないといってもよさそうです。入出力のパフォーマンスについては十分な考察や実証をおこなっていません。

プログラムの流れは、

  1. entokenize :: B.ByteString -> [[I]]: 標準入力全体を入力トークンのリスト(行)のリストに分解
  2. decode :: [[I]] -> Dom: 入力トークンのリストのリストから、solve関数の入力データを構成
  3. solve :: Dom -> CodomDomが入力データの型、Codomが出力(解答)データの型
  4. encode :: Codom -> [[O]]solve関数の出力データから、出力トークンのリストのリストを構成
  5. detokenize :: [[O]] -> B.ByteString: 出力トークンのリストのリストをまとめて標準出力に置くデータを構成

競技者は、

  1. 入力トークンの型IAsToken型クラスのインスタンスを宣言済みの型(B.ByteStringStringCharIntIntegerDouble)のうちどれか1つに決定
  2. 出力トークンの型OAsToken型クラスのインスタンスを宣言済みの型(B.ByteStringStringCharIntIntegerDouble)のうちどれか1つに決定
  3. solve関数の入力の型Domを決定
  4. solve関数の出力の型Codomを決定
  5. decode :: [[I]] -> Domを実装
  6. encode :: Codom -> [[O]]を実装

します。entokenizedetokenizeAsToken型クラスのメソッドですので、AsToken型クラスのインスタンスを宣言済みの型に関しては実装する必要はありません。

インポート宣言

使いそうなモジュールをインポート宣言に加えてあります。各自必要に応じてカスタマイズしてください。
ここでインポートできモジュールは、package.yamldependenciesに記述されているパッケージに含まれているものです。
また、

https://hackage.haskell.org/package/ac-library-hs

にあるモジュールもインポート可能です。

デバッグプリント

app/Main.hs 37行目 debug = () /= ()debug = () == () に書き換えると、trace :: String -> a -> a(127-129行目)およびtracing :: Show a => a -> a(131-132行目)が機能するようになります。

メッセージ付きエラー例外

app/Main.hs の135-136行目impossible :: String -> a、138-139行目invalid :: String -> a

盆栽

自分用の盆栽コードを追加する場合は、

  • 盆栽に必要なインポート宣言は、必要に応じて、所定の場所に追加
  • 盆栽コード本体は、{- Bonsai -} 以降に追加

してください。

Discussion