Haskell-servant,Elm,Material UIの構成でダッシュボードを作る。

ダッシュボードを作りはじめる。

 

REST APIサーバー側をHaskell-servantで用意したので、サーバー側プログラムはここで一段落。
それに接続するクライアント側をElm,elm-mdl(MaterialUI)で作ろうと思います。

Elmに入門

APIサーバーはHaskell-servantなので、クライアント側はservant-elmにElmの型を作ってもらってElmで書くことにした。
(JavaScriptではフレームワークの選択に迷ったから。種類が多過ぎなんだよ)

Elmは今回始めて使うが、Haskellの影響が強いようなのでHaskellの知識だけでやりくりした。

(お互いコンパイルが出来たら大体うまくいく、そんな気持ち)

ElmはThe Elm Architectureしか選べないので、ここの選択に迷わないという良さがあるね。

ダッシュボード(開発中)

マテリアルUIでシングルページアプリケーションにしておきました。
今のところ#付きのアドレスで無いから、URLに直接アクセスすると、サーバーが404を返す制約がある。
(Webサーバーの方でアクセスを全てルートにリダイレクトする設定にしなければね)

ビルド方法

サーバー側Haskellプログラム
~/tractor/ > stack install
Copying from tractor/.stack-work/install/x86_64-linux/lts-11.7/8.2.2/bin/tractor to .local/bin/tractor

Copied executables to .local/bin:
- tractor

初回実行時は恐ろしく時間が掛かるのでそのつもりでいること。(GHCのダウンロードから始まるから。)

Haskellプログラムからservant-elmでElm側のAPI型を自動生成すると同時にservant-docでAPIドキュメントを自動生成する
~/tractor/ > stack test --skip tractor-test
tractor-0.4.5: unregistering (dependencies changed)
tractor-0.4.5: configure (lib + exe + test)
Configuring tractor-0.4.5...
tractor-0.4.5: build (lib + exe + test)
Preprocessing library for tractor-0.4.5..
Building library for tractor-0.4.5..
Preprocessing test suite 'code-gen' for tractor-0.4.5..
Building test suite 'code-gen' for tractor-0.4.5..
[1 of 2] Compiling Main             ( code-generator/Main.hs, .stack-work/dist/x86_64-linux/Cabal-2.0.1.0/build/code-gen/code-gen-tmp/Main.o )
[2 of 2] Compiling Paths_tractor    ( .stack-work/dist/x86_64-linux/Cabal-2.0.1.0/build/code-gen/autogen/Paths_tractor.hs, .stack-work/dist/x86_64-linux/Cabal-2.0.1.0/build/code-gen/code-gen-tmp/Paths_tractor.o )
Linking .stack-work/dist/x86_64-linux/Cabal-2.0.1.0/build/code-gen/code-gen ...
Preprocessing executable 'tractor' for tractor-0.4.5..
Building executable 'tractor' for tractor-0.4.5..
tractor-0.4.5: copy/register
Installing library in tractor/.stack-work/install/x86_64-linux/lts-11.7/8.2.2/lib/x86_64-linux-ghc-8.2.2/tractor-0.4.5-LCTypwMspXv7MgRanjzRRT
Installing executable tractor in tractor/.stack-work/install/x86_64-linux/lts-11.7/8.2.2/bin
Registering library for tractor-0.4.5..
tractor-0.4.5: test (suite: code-gen)
             
Progress: 1/2Writing: elm-src/Generated/WebApi.elm
             
tractor-0.4.5: Test suite code-gen passed
Completed 2 action(s).
~/tractor/ > 

skipしているのは本体のテストスイート。初回なら実行してもいいかもね。

Elmをビルド
~/tractor/elm-src/ > make
elm-make --yes Main.elm --warn --output=public/main.js
Success! Compiled 5 modules.                                        
Successfully generated public/main.js
~/tractor/elm-src/ > 

ビルド結果(一部省略)

.
├── LICENSE
├── README.md
├── Setup.hs
├── app
│   └── Main.hs
├── code-generator
│   └── Main.hs
├── conf.json
├── elm-src
│   ├── Generated
│   │   └── WebApi.elm
│   ├── Main.elm
│   ├── Makefile
│   ├── Model.elm
│   ├── Msg.elm
│   ├── Route.elm
│   ├── View.elm
│   ├── elm-package.json
│   ├── elm-stuff
│   └── public
│       ├── WebApiDocument.md
│       ├── assets
│       │   └── GitHub-Mark-32px.png
│       └── main.js
├── makeTechnicalWithTA-lib.c
├── package.yaml
├── server-test.ipynb
├── src
│   ├── BackOffice
│   │   ├── Agency.hs
│   │   ├── StockQuotesCrawler.hs
│   │   └── TechnicalIndicators.hs
│   ├── BrokerBackend.hs
│   ├── Conf.hs
│   ├── GenBroker.hs
│   ├── GenScraper.hs
│   ├── KabuCom
│   │   ├── Broker.hs
│   │   ├── Model.hs
│   │   └── Scraper.hs
│   ├── Lib.hs
│   ├── MatsuiCoJp
│   │   ├── Broker.hs
│   │   ├── Model.hs
│   │   └── Scraper.hs
│   ├── Model.hs
│   ├── ModelDef.hs
│   ├── NetService
│   │   ├── ApiTypes.hs
│   │   ├── PubServer.hs
│   │   └── WebServer.hs
│   ├── SBIsecCoJp
│   │   ├── Broker.hs
│   │   ├── Model.hs
│   │   └── Scraper.hs
│   ├── Scheduling.hs
│   ├── SinkSlack.hs
│   └── VerRev.hs
├── stack.yaml
├── stock-charts.ipynb
├── taFromHiSpeedCSV
├── test
│   ├── ConfSpec.hs
│   ├── KabuCom
│   ├── MatsuiCoJp
│   ├── SBIsecCoJp
│   ├── Spec.hs
│   └── conf.test.json
├── tractor.cabal
└── tree.txt

186 directories, 598 files

サーバーの起動

~/tractor/ > tractor       
Missing: (--webapi | --standalone | --normal)

Usage: tractor [--conf CONFIG_FILE] (--webapi | --standalone | --normal)
    • APIしかいらないなら –webapi
    • API不要なら–standalone
    • 両方必要なら–normal

を選択して動かしてください。
例えば

~/tractor/ > tractor --webapi

の状態でlocalhost:8739にアクセスすると上のダッシュボードに入れます。

感想

自分はC言語チョットワカルけれど、C言語で文字列操作するエグさを知っているから純粋関数型言語に逃げたわけなのですが、
Haskell + Elm はいいよね、コードが明らかに減るから。関数型プログラミングは宣言的プログラミングに近いからなんだけど。

 

例えばプログラマ適性を見るFizz Buzzテストで変数, forループ, if, mod(%), 出力が扱えるかを見るテストのようだけど。

自分はプログラマ適性が無いので、いちいちループ書くのが面倒だから問題文そのまま書いて

#/bin/sh
Fizz (){
    sed '0~3c\Fizz'
}
Buzz (){
    sed '0~5c\Buzz'
}
FizzBuzz (){
    sed '0~15c\Fizz Buzz'
}
seq 1 100 | Fizz | Buzz | FizzBuzz

手元のsh/bashでこのスクリプトを動かせば

~/ > ./fizzbuzz.sh | head -n 20
1
2
Fizz
4
Buzz
Fizz
7
8
Fizz
Buzz
11
Fizz
13
14
Fizz Buzz
16
17
Fizz
19
Buzz

こうなるから、ループも変数も別に必要ないよねって思う(面倒な物は処理系に押しつけて、自分は要点しか書いていないから自ずとコードが短くなる)

 

こんな小ネタを挟んでいるのは、自分がElmが説明できるほどによく分っていないから。

説明は無しの方向です。(コードが見たいならGitHubへどうぞ)

 

コメントを残す

メールアドレスが公開されることはありません。