Haskellでわかる群論の代数的構造をやってみました。

私は数学の教科書で問題を解こうとすると眠くなります。けれど、プログラミングになると眠くなりません。なので、代数の基本をプログラミングで試せるaiya000さんのgitbook「Haskellでわかる群論の代数的構造」をやってみました。

gitbookは群、グループまで書かれていますが、ソースコードのほうは環、リングまで書かれていました。

stackの場合、.cabalファイルにhspecとQuickCheckと書くと、すぐに使えて、stack build –testで、ビルドとテストを実行できます。

hw.cabalについて

.cabalファイルには、src/Group.hs、src/Semigroup.hsのようにモジュールを追加したら(ここでいうモジュールとは、ファイル一行目のmodule Group whereの事)、そのたびにexposed-modulesに追加していきます。

あとは、test-suite hw-test:のところには、build-dependsにhspecとQuickCheckを追加しました。

 

src/Group.hs

test/GroupSpec.hs

Spec.hs

 

まとめ

プログラミングの場合は、言葉の定義を何回も見返したりして、それをコメントに書いて、さらに実装しテストをするので、思っていた以上に数学に対して、抵抗なく学んでいけています。

今回は、Haskell,Stackという構成なので、近いうちにgithubにアップロードしたいと思います。

Windows10+Stack+ATOMでのトラブル対応

ghc-modをインストール時などで、old-timeのビルドエラーが発生する場合

私の場合は、Windows10にHaskell Platform 8.0.1 を再インストールしたり、stack install ghc-modコマンドを実行したときに発生しました。

https://github.com/haskell/old-time/issues/3

Haskell Platformは、インストール後、システム環境変数PATHに以下を追加します。Haskell PlatformはmingwとmsysというLinuxのツール群も一緒にインストールされます。しかしmsys\usr\binはなぜかPATHに設定されません。old-timeはこれがあればビルドができます。

システム環境変数PATH

  • C:\Program Files\Haskell\bin
  • C:\Program Files\Haskell Platform\8.0.1\lib\extralibs\bin
  • C:\Program Files\Haskell Platform\8.0.1\bin
  • C:\Program Files\Haskell Platform\8.0.1\mingw\bin

また、Stackのインストールで、ユーザー環境変数PATHにも以下が設定されます。

  • C:\Users\xxxxxxx\AppData\Roaming\local\bin

システム環境変数PATHに以下を追加しましょう。

C:\Program Files\Haskell Platform\8.0.1\msys\usr\bin

ATOMのghc-modでエラーが出るときの対応方法

ATOMエディターのhaskell-ghc-modパッケージは、エラーのスタック情報を表示するだけなので凄くわかりづらいです。それで、このエラーはhaskell-ghc-modの不具合ではなく、ghc-modがエラーを出している場合があります。つまりATOM側の問題ではないです。

そのため、非常に面倒ですが、PowerShellでghc-modコマンドを実行すると解決できる場合があります。

ghc-modで、hGetContents: invalid argument (invalid byte sequence)が発生する

これは何も設定せずにstackを使った場合、.hsファイルのコメントに日本語があった場合でも発生します。

ghc-mod: C:\Users\xxxxx\workspace_haskell\hw\src\Semigroup.hs: hGetContents: invalid argument (invalid byte sequence)

まさかデフォルトでUTF-8のhsファイルに日本語のコメントを書けないとは思わなかったので、最初はATOMエディターのhaskell-ghc-modのバグと思ってました。

HSpecテストを試してみたら、ghc-modでエラーが発生した。

StackでHSpecを使う入門サイトなどを調べていると、Spec.hsに以下を記述すれば自動でSpecファイルを検知してくれると書かれています。

これだけだと、ATOMエディターで上記画像のような赤いエラーメッセージが表示されました。対応としては、hspec-discoverをstack経由でインストールします。

 

StackでHSpecでstack testを実行するとHUnit、QuickCheckも用意される?

Stack を使って Haskell したい!! を参考にHSpecを書いてみました。.cabalファイルのbuild-dependsにhspecを追加して、コンソールから、stack testを実行したら、依存関係で、HUnit、QuickCheckもダウンロードしてビルドされているようです。

プロジェクトの.cabalにhspec追加

 

Lib.hs

LibSpec.hs

Spec.hs

 

cabalでtest-suiteを作ってみます。

HaskellではHSpec、HUnitなどテストツールがありますが、まずはcabalファイルの書き方が分からないので、ライブラリー用のプロジェクトを作って試してみました。

テストツールは使わず、srcフォルダーとtestフォルダーでソースコードを分けて、test側がsrcのモジュールをロードして実行するだけです。

環境

  • Windows10
  • Haskell Platform 8.0.1
  • Cabal 1.24.0.0
  • Powershell

 

プロジェクト作成

プロジェクトはlibrary用にしました。

src/MyUtil.hs

test/Main.hs

my-project.cabal

cabal initをした時点では、my-project.cabalにはtest-suiteなどはないので上記のように追加します。ポイントとしては、テストされる側でexposed-modules: MyUtilのように指定することと、test-suite側では、build-depends: my-projectを追加することです。

設定の読み込み

テスト

まとめ

これをやってみたことで、cabalファイルが分かってきました。またcabalは初期設定でテスト用フォルダーなどを作らず、設定を調べるのも結構時間がかかるので、とりあえずてすとしたいなら、stackを使ったほうがよさそうです。

 

cabalをちょっと使ってみた感想

昨日まで、Windows10でHaskell+ATOMエディター+プロジェクト管理ツールStackを使ってみて、ATOMでghc-modがうまく動かず、一度すべてアンインストールして、Windows10+Haskell+Cabal+ATOMエディターという環境を構築してみました。

使ってみて良かったところ

  • 速い
  • ATOMで問題なくghc-mod使える
  • .cabalファイルが何か分かった。

cabalとstackの関係

Haskellでは2015年ごろにstackというツールができて、最近はこれが推奨されているようです。stackコマンドでプロジェクトを作成して、ビルド、テスト、ライブラリ依存管理などができます。

それ以前まではcabalが使われていました。現在のcabalはsandboxという機能でプロジェクト単位にライブラリーのバージョン管理ができますが、初期のcabalはOSのアカウントでライブラリー管理をするため、異なるプロジェクトや、githubからとってきたプロジェクトで、ライブラリーのバージョンを調整する必要があり大変だったそうです。

https://sites.google.com/site/toriaezuzakki/haskell/environment#TOC-sandbox-

cabalのしんどいところ

stackではプロジェクトを新規に作成したらテスト用のフォルダーも作成してくれてすぐテストができますが、cabalは設定ファイルを書いて用意する必要があるため面倒です。

公式のユーザーガイドも出来があまりよくなく、依存関係をどう書いていけばいいかわかりません。

https://www.haskell.org/cabal/users-guide/developing-packages.html#test-suites

いろいろ調べていて以下を見つけました。

http://taylor.fausak.me/2014/03/04/haskeleton-a-haskell-project-skeleton/

これを参考にしようと思ったのですが、これを今から試すならstackやったほうがよさそうです。

Windows10にATOM+Haskell+Cabel環境を構築する

Windows10でStackの環境を構築しましたがghc-modがATOMでうまく動かず、Stackも重すぎたので断念しました。

Haskellのインストール

Haskell+Cabalの場合は、おそらくWindowsでも問題ないはずなので、こちらを構築してみます。まずは、HaskellのMinimal installersでHaskellをインストールします。インストール時にいろいろ選択肢がありますが、Stackは使わないのでインストールしませんでした。

ghc-modのインストール

上記をインストールすると環境変数の設定もしてくれるので、ghcコマンド、cabalコマンドが使えるようになっています。そのためこの時点でHaskellの開発は問題なくできます。

cabalはパッケージ管理で、ghc-modとエディターを組み合わせると開発効率が良くなるので、cabalからghc-modをインストールします。

上記のように、old-time-1.1.0.3の依存関係のインストールに失敗してghc-modがインストールできません。

cabal/configの修正

Haskell Platformをインストールすると内部では、MSYS+Cygwinのコマンドやライブラリーなどが同時にインストールされますが、それらはパスが通ってません。そのため以下のように、パスを設定します。

configファイルは、C:\Users\*******\AppData\Roaming\cabal\configにあります。configファイルは、–がコメントです。

50行目付近

これでひとまず、ghc-modがインストールできるようになりました。cabalの使い方を調べてみます。

インストール先

C:\Users\*******\AppData\Roaming\cabal\bin

Haskell Platformをインストールしたときにこの環境変数にパスが通っているため、cabalコマンドでインストールしたものがすぐにコマンドプロンプトやPowerShellで使えます。

hlintとstylish-haskellをインストール

以下などを参考にインストールします。

http://qiita.com/manji-0/items/463ea051f624a9a4a83a

cabalの簡単な使い方

ビルド

実行

テスト

テストは、テスト用のライブラリーを追加したりする必要がありますが、cabal install でライブラリーをインストールした後は上記コマンドとエディターが開発していけます。

実際には、cabal runで、ビルドされていない場合は、cabal buildが実行されるので、修正してcabal runでよさそうです。

ATOM+Haskell+Cabal環境をWindows10で構築して

Stackがとても重く、ATOMでghc-modが動かなかったのが嘘のように快適です。cabal runを実行してコンパイルが実行されても許容範囲でコンパイルが終わる(当たり前ですが…)のでストレスがありません。「すごいHaskellたのしく学ぼう!」ぐらいのレベルの人は、まだStackはインストールしないほうが良いです。

Windows10のStack+ATOMのHaskell環境を断念

Windows10にStack+ATOMのHaskellの環境構築」でHaskellがプログラミングできる環境を用意しましたが、ATOMでghc-modがうまく動かず、Stackが重すぎるのでこの構成で使うのはひとまずやめることにしました。

ATOMでghc-modがうまく動かない

初心者レベルで文法を学んだ時の感想ですが、ATOMが非常にもっさりしています。私のPCは最近の3Dゲームがある程度動くような環境で、Visual Studio CodeやVisual Studioなどは問題なく動作するので、ATOM側にいろいろ問題がありそうです。(https://github.com/atom-haskell/haskell-ghc-mod/wiki/Using-with-stack)

Windows10でHaskellのStackが重すぎる

Stackが重すぎます。ファイルが1つ、2つで関数が数個しかないのに、stack buildコマンドでビルドすると数秒待たされます。stack exec helloworld-exeでも数秒待たされます。Stackはプロジェクト管理ツールとしてテンプレートを用意してくれるため「これだ!」って思ったツールなので使っていきたいのですが、如何せん重すぎて使えません。

仮想環境にUbuntus/emacs/cabelの環境があるので結局それを使いますが、Windows10ですべてアンインストールしてcabal環境も作ってみようと思います。

 

 

比較した結果、ANTLR4の開発環境はEclipseのANTLR4 IDEが最も良い

数日前まで、関数型プログラミング言語F#で、HaskellのパーサーコンビネータPersecを移植したFParsecを試していました。F#を使っていくうちに再帰処理も当たり前に実装できるようになったため、JavaのパーサージェネレータANTLR4に挑戦しました。

ANTLRではいくつか開発環境があるので、簡単な四則演算の計算機を作って開発環境を評価してみました。結論から言うとEclipse 4.6.1 + 「ANTLR4 IDE」が最も良いです。良い理由は以下です。

  1. 保存時にコンパイルが実行される。
  2. 編集中にリアルタイムで、シンタックスダイアグラム表示。(あとで画像説明します。)
  3. ParseTreeビューで、書いたパーサををすぐ試せる。

詳細な説明は後からgifキャプチャーと共にしますが、シンタックスハイライトと文法チェックがないとちょっとしたミスで時間を取られすぎます。コマンドラインとメモ帳などは時間の無駄なのでやめましょう。

試した開発環境

  1. Visual Studio Code + 拡張機能「ANTLR4 grammar syntax support」
  2. IntelliJ IDEA 2016.3.1 + プラグイン「ANTLR v4 grammar」
  3. Eclipse 4.6.1 + 「ANTLR 4 IDE 0.3.6」
  4. Eclipse 4.6.1 + 「AntlrDT 4.3.1」

 

Visual Studio Code + 拡張機能「ANTLR4 grammar syntax support」
ハイライトのみでシンタックスエラーなどは検知できません。

Visual Studio Codeの拡張機能では、ハイライト表示だけで、文法チェックなどはできませんでした。

IntelliJ IDEA 2016.3.1 + プラグイン「ANTLR v4 grammar」

IntelliJのプラグインは、リアルタイムで文法チェックができ、文法ファイルから問題なくJavaファイルを生成できたら、ANTLR Preview(二枚目の画像)ですぐにテストもできます。また.g4拡張子のファイルがANTLRのファイルと認識されるので、通常のJavaプロジェクトにそのまま配置できます。

リアルタイムで文法チェック
すぐにパーサーをテスト可能
コンテキストメニューから、ファイル生成と設定が可能
Javaプロジェクトにg4拡張子のファイルを置くだけ

上記は、Javaプロジェクトを作成して、g4フォルダーを作って、そこに.g4拡張子のANTLRファイルを置きました。設定で.g4の出力ファイル先をsrc/simpleに向けているので、パーサーを作成した後すぐにJavaで実行することができました。

注意点としては、このプラグインをインストールしても、Javaプロジェクトにantlrライブラリーのクラスパスが通るわけではないので、別途公式からantlrライブラリーをダウンロードしてきて設定する必要があります。

Eclipse 4.6.1 + 「AntlrDT 4.3.1」

こちらは初心者向けではありませんでした。初期設定で、レキサーとパーサーが分けられたファイルが生成されます。また.g4ファイル内にJavaのソースコードを直接埋め込むことも可能ですが、字句解析、構文解析を学ぶ上では、まずは、簡単な文法ファイルと、そこから生成したJavaファイルを、Javaプロジェクトで実行したほうが各作業が独立していてわかりやすいです。そのためはじめANTLRを使う方にはこの拡張機能はお勧めしません。

Eclipse 4.6.1 + 「ANTLR 4 IDE 0.3.6」

ANTLR4 IDEもリアルタイムに文法チェックが動作するので非常に効率が良いです。

リアルタイムに文法チェック

パーサージェネレーターを学ぶ上で大変なのは、ちょっとした文法ミスなどを見つけづらい事です。とくに字句解析、構文解析を学び始めた段階では、エディターとコンパイラーのみだと記号の書き忘れなど簡単なミスで結構な時間を取られます。

以下のように、リアルタイムにSyntax Diagramを表示しくれると、今どこが意図したとおりに実装されていて、どこに誤りがあるかが明確になります。

Syntax Diagramで視覚的に分かりやすい
Parse Treeですぐにテスト!

ある程度文法を作成したら、その文法をエディターで選択すると、ParseTreeビューに、[Calc::calc]のように表示されます。その下の入力欄に、適当な入力をすると構文木が作成されて意図した実装になっているかすぐに確認できます。

実際に入力してみると、リアルタイムでチェックが実行されているので、「1 +」のように途中の場合は、エラー表示がされます。上記ではエディターでcalcを範囲選択しましたが、exprやnumberの部分も選択可能です。なのでexprなど小さな構文をまずテストして、そのあとに、Calc::calcをテストするのが普通です。

設定はプロジェクト単位

この拡張機能は、プロジェクト単位で設定するようです。ANTLRプロジェクトを作成できますが、Javaプロジェクトを作成して、antlr4など適当なフォルダーを作成して、Calc.g4のようにファイルを保存しても問題なく使えます。

Javaプロジェクトに.g4ファイルを置いても問題ない。

プロジェクトを右クリックしてコンテキストメニューからPropertiesを選択すると、以下PropertiesダイアログからANTLRの出力先を指定できるので、./srcにします。ANTLRによって生成されたJavaファイルがEclipseにより自動でコンパイルされて、./binフォルダーにクラスファイルが作成されます。あとはこれを呼び出すクラスを作成していけばよいです。

まとめ

ANTLR4の開発環境の評価をしました。ふだんIntelliJで開発していてもANTLR4の場合はEclipseでやったほうがよさそうです。

FParsecのチュートリアルでJSONParserをVisualStudio2015で実行する方法

Haskellのパーサーライブラリーparsecは、いろんな言語に移植されていてF#でもFParsecがあります。今回はVisual Studio 2015で、FParsec 日本語チュートリアル – a wandering wolf を試してみました。

使ってみた感想

まさか自分でJSONパーサーを作って動かすことができるような日がくるとは思ってもみなかったのでとてもうれしいです。関数型プログラミングを勉強すると再帰をたくさん使うので、以前よりBNFの再帰構造にも抵抗なく取り組めました。まだ使い慣れていないので、難しい問題に取り組むよりかは、iniファイルなどを自分で実装してみたいです。

FParsec,FParsecCSをロードする方法

F#でfsファイルを使うときにF# InteractiveにDLLライブラリーをロードさせる方法 手動で、FParsec,FParsecCSをロードする方法を上記に書いています。

参照設定を手軽にfsxファイルに取り込む方法

ソリューションエクスプローラの[参照設定]を右クリックすると[Generate References for F# Interactive]がコンテキストメニューに表示されるのでそれを右クリックスト、Scriptsフォルダーが作成され、load-project-debug.fsx、load-references-debug.fsxが作成されます。load-project-debug.fsxの中で、load-references-debug.fsxを読んでいます。私たちがfsxで読み込むのは、load-project-debug.fsxになります。

この例のように、CSVParserプロジェクトで、HelloParser.fsxなどを新規作成する場合、fsxファイルに、以下のような#load文を書けばロードできるようになります。注意点としては、Scripts/のようにScriptsフォルダーを指定しないといけない事です。

参照設定は、NuGetでライブラリーを取得したり、既存のライブラリーを参照に追加した場合のみへんこうされます。なので面倒ですがそのたびにこの手順を踏む必要がありそうです。

load-references-debug.fsxの書き換え

[Generate References for F# Interactive]で、load-references-debug.fsxを生成した時は、以下のように、FPharsec.dll、FParsecCS.dllという順番になっています。

FPasrsecのDLLは、FParsecCS.dll、FParsec.dllの順番でF# Interactiveに読み込ませる必要があるので、コピーペーストで、FParsecCS.dllとFParsec.dllの順番を入れ替えます。

これで、Ctrl+Aでファイルを全選択して、Alt+Enterで、F# Interactiveにファイルを流し込めます。

文法の単純な見落としに注意

以下が正しいソースコードですが、

以下のように書いて、コンパイルエラーが取れずに頭を抱えてしまいました。

F#では、リストの区切り文字は、セミコロンで[要素1;要素2;要素3]のように記述します。また、複数行にした場合は、セミコロンを省略できます。よって、以下2つは同じです。

普段、Ctrl+K,Ctrl+Dで整形をしますが、以下のような書き方だと、当たり前ですがフォーマッターは、要素1の引数と判断してしまい、整形することはできません。

jobjectの書き方やFPharsecのライブラリーのロードに問題があると思いずっとそちらを調べていたのですが、実際は単純な文法エラーでした。

 

チュートリアルを試した感想としては、もし問題が発生した場合はソースコードをソースコードの入手方法

FParsec Documentation – 3 Download and installation の3.2の部分に以下の引用がありソースコードがFParsecのzipファイルがありその中のSamples/JSONに今回のサンプルのソースコードがあります。

You can “clone” the source code using Mercurial (HG) or you can download it as a zip‐file.

 

ソースコード

最後の行に、runParserOnFileで、実行する行を追加しています。

FSharpでmatch式をつかった直積の書き方

JavaやC#の場合、二重のfor文を実行すれば、x,yの直積が完成します。F#でもリストの内包表記で、二重のforにより直積が作れます。関係代数について調べていた時に、stackoverflowにmatch式を使った直積の書き方を見つけました。

関係代数やリレーショナルデータベースは、集合と関係してくるので、数学の集合論や関数型プログラミングで写像とかで学んだ知識がそのまま使えるのはうれしいです。

http://www.cs.reitaku-u.ac.jp/infosci/rdb/rdb02.html

関係代数