Haskell入門のコンソールアプリを作るの備忘録

# はじめに

この記事はHaskell入門を元にコンソールアプリを作るうえで書籍に登場しない情報をまとめたものです。
Haskell入門は2017年に書籍化されており、現状書籍の通りに記述していってもエラーになります(した)。
個人的には覚えたいならエラー取りつつ進めばいいと思ってるので問題ないのですが、
今後自分がHaskellに再入門する際に同じ轍を踏まないよう文書化しました。

もちろん書籍にはサンプルコードが存在しており、問題発生時にはサンプルコードを元に読み進める事ができるようになっています。
Haskell勉強したい方はHaskell入門とかもっと頭いいひとの記事を読んでください。

![haskell.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/42445/cb037792-7849-6490-45c3-5b03a2a91c36.png)
<font color="dark_pink">特に書くことが無かったのでHaskell書きました</font>

# 9.1 開発の準備

書籍では下記コマンドを実行すると基本のディレクトリが作成されるとの事で、ディレクトリのツリーも記載されている。

```bash
stack new hjq
```

実際には下記差異がある。

 + ChangeLog.md
 + package.yml
 + README.md

# 9.2 HUnitによる自動テスト

とくに変更なし

# 9.3 パーサの作成

## 9.3.1 フィルタのデータ定義とテスト

テストを書いて初めてのstack runすると、Testが無いと怒られる。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/42445/e1a6c613-d353-152a-9731-a187b1da96b1.png)

下記対策が必要となる。

 + src/Lib.hsを削除
 + hjq.cabal編集
   + Library.exposed-modules
     + Lib削除
     + Data.Hjq追加
     + Data.Hjq.Parser追加
     + Data.Hjq.Query追加
   + Library.build-depends
     + text追加
 + test/Spec.hs
   + 先頭に`{-# LANGUAGE OverloadedStrings #-}`追加
   + 下記モジュールをインポート
     + Test.HUnit
     + Data.Hjq.Parser
     + Data.Hjq.Query
 + src/Data/Hjq.hs
   + 先頭に`module Data.Hjq where`追加
   + parseJqFilterを削除
 + src/Data/Hjq/Parser.hs
   + 先頭に`module Data.Hjq.Parser where`追加
   + 下記モジュールをインポート
     + Data.Text
 + src/Data/Hjq/Query.hs
   + 先頭に`module Data.Hjq.Query wher`追加
   + 適当に関数追加 
 + app/Main.hs
   + `import Lib`削除
   + mainの中身を適当に書き変える(someFuncを使わない)

## 9.3.2 フィルタ文字列のパーサを書く

 + hjq.cabal
   + library.build-depends
     + attoparsec追加
 + src/Data/Hjq/Parser.hs
   + 先頭に`{-# LANGUAGE OverloadedStrings #-}`を追加
   + 下記モジュールをインポート
     + Data.Attoparsec.Text
     + Control.Applicative 

上記修正でテストが通る。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/42445/1dc45aee-c2c4-98fb-3715-340cfb37a437.png)


## 9.3.3 クエリのデータ定義とパーサ

 + test/Spec.hs
   + mainのテストケースに`jqQueryParerTest`を追加 

上記が無いとテストが呼ばれない。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/42445/86766ba7-e2fa-798d-d785-5d454d66d595.png)

# 9.4 クエリの実行とIO処理

## 9.4.1 lens-aesonによるJSON操作

とくに変更なし

## 9.4.2 フィルタの実行関数

 + test/Spec.hs
   + mainのテストケースに`applyFilterTest`を追加
   + import
     + Control.Lens
     + Data.Monoid
     + Data.Text
     + qualified Data.Vector as V
     + qualified Data.HashMap.Strict as H
     + Data.Aeson
     + Data.Aeson.Lens
 + src/Data/Hjq/Query.hs
   + 先頭に`{-# LANGUAGE OverloadedStrings #-}`を追加
   + import
     + Control.Lens
     + Control.Monad
     + Data.Hjq.Parser
     + Data.Aeson
     + Data.Aeson.Lens
     + Data.Text as T
 + hjq.cabal
   + library.build-depends
     + vector追加 
     + unordered-containers追加
     + aeson追加
     + aeson-pretty追加
     + lens-aeson追加
     + lens追加
   + test-suite.build-depends
     + text追加
     + unordered-containers追加
     + vector追加
     + aeson追加
     + aeson-pretty追加
     + lens-aeson追加
     + lens追加

## 9.4.3 クエリの実行関数

とくに変更なし

## 9.4.4 処理のまとめとI/O

 + hjq.cabal
   + library.build-depends
     + errors
     + bytestring
   + executable.build-depends
     + bytestring
     + text
 
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/42445/8e1dcde1-ae1e-5413-e89b-de3fca29700b.png)
<font color="dark_pink">やったぜ(できてない)</font>

# ふりかえり

手続き型言語のみをやってきた人間にとって、関数型言語を学ぶのは非常に時間がかかる。
経験が邪魔をする。`これはxxで言うyy`がまったく通用しない。
まぁ、概念を学ぶのは時間がかかって当たり前なので、逆にゆっくりのんびり学ぶ決意が固まった。

いずれ人にHaskell勧められるぐらいになれるといいなぁー。