LoginSignup
1
1

More than 5 years have passed since last update.

gitでローカルに取得したHaskellパッケージを使って、自作実行環境から使ってみる

Last updated at Posted at 2017-05-06

初めての投稿

こちらの記事を参考に、Hackage公開ではないHaskellパッケージを利用して、動かしてみる。
とにかく、超初心者だったけれど、stackと、それが提供してくれるデフォルトプロジェクトの作成方法、そこに出来上がるもの、.cabalファイルってどれ? Main.hsってどこ?などについての知識を仕入れた段階で挑戦。

環境

Ubuntu (使い慣れていません…)

準備

  • Stackをインストールしておく。
  • ライブラリのインストール(いつやったのか、覚えていない)
sudo apt install liblapack-dev libblas-dev

使いたいけれど、Hackageにないパッケージの入手

Hackageにあれば、.cabalファイルに書き込めば stack コマンドで取れるけれど、そうは行かないので、ローカルに取ってきて、そのローカルに置かれたパッケージを.cabalに指定することにする

git でパッケージを取得

~/test/ 以下で作業することとする

git clone https://github.com/adscib/monad-bayes

これで、~/test/monad-bayes/

ができる。この中に、monad-bayes.cabalファイルもあれば、src ディレクトリ、app ディレクトリもある。

この monad-bayes.cabalには山のように必要なモジュールを取るための情報が書かれている。

~/test/monad-bayes/
以下で次をやる。

stack haddock
stack haddock --open

これで、monad-bayesパッケージの情報をブラウザで見られるようになる。

実行環境の準備

自分でmonad-bayesパッケージを使って実行する環境を作る。

これも、stackを使って作る。

~/test/ で

stack new mbplay

する。
~/test/mbplay/
ディレクトリができ、その下に、
mbplay.cabalファイルができ、

~/test/mbplay/app/ 以下に、Main.hsができ
~/test/mbplay/src/ 以下に、Lb.hs ができる。

Main.hsは実行可能ファイルを作らせる「根っこ」のファイル。

srcディレクトリに、このmbplayプロジェクトのためのモジュールファイルを置くことにする。

mbplayのstack.yaml ファイルの書き換え

今、このプロジェクトのディレクトリは
~/test/mbplay/ であって、使いたいパッケージは
~/test/monad-bayes/ にあるので、

相対パスで、monad-bayesパッケージの頂上のディレクトリを指定する

packages:
- '.'
- location:
    "../monad-bayes" # さっき clone したディレクトリ
  extra-dep: true    # 依存先(本体の一部じゃなくて)として扱ってもらう

mbplay のmbplay.cabal ファイルの書き換え

このプロジェクトで、ローカルに置いたmonad-bayes パッケージを使いたいので、それを指定する。

使う場所は、Main.hsかもしれないし、ローカルモジュールたちかもしれないので、mbplay.cabalファイルのそれぞれを管轄する部分にmonad-bayesを指定する。

~/test/mbplay/src/ 以下のローカルモジュールのファイル内でimportできるようにする。

library  
  hs-source-dirs:      src
  exposed-modules:     Lib
  build-depends:       base >= 4.7 && < 5
                     , monad-bayes
  default-language:    Haskell2010

~/test/mbplay/app/ 以下にあるMain.hsでもimportできるようにする。

executable mbplay-exe
  hs-source-dirs:      app
  main-is:             Main.hs
  ghc-options:         -threaded -rtsopts -with-rtsopts=-N
  build-depends:       base
                     , mbplay
                     , monad-bayes
  default-language:    Haskell2010

ここまでがうまく行っているかを確認

その1

この段階では、mbplayプロジェクトのMain.hsは、その中から、~/test/mbplay/Lib.hs をimportして、その中の関数を実行するようにできている。

~/test/mbplay/

以下で

stack install

とすると
mbplay-exe という実行可能ファイルができるが、まず、それをやってみる。

mbplay-exe

とやると、コンソールに"someFunc"という文字列が現れる。

その2

ついで、~/test/mbplay/Lib.hs
を次のように書き換える。

module Lib (someFunc) where
import Control.Monad.Bayes.Simple

このControl.Monad.Bayes.Simple は、今、使いたいと思っているmonad-bayesパッケージの中にあるものなので、このimportがうまく行けば、パッケージ利用環境はOKと解る。

この状態で

stack build

して、無事にコンパイルが終わればOK。

monad-bayesパッケージを利用

さて、本番。

monad-bayesパッケージを使うために、以下をする。

自作モジュールを作る

monad-bayesパッケージでは、

~/test/monad-bayes/test/
というディレクトリがあり、その中にいくつかのhoge.hsファイルがある。
これらは、~/test/monad-bayes/test/src/にあるわけではないので、モジュールとして参照できない(多分)。

なので、この~/test/monad-bayes/test/models/ 以下に置かれた Dice.hsというファイルを使った処理をmbplayの方でやって見ることにする。

~/test/mbplay 以下にいるとして、次のようなコマンドで

~/test/monad-bayes/models/Dice.hs

~/test/mbplay/src/Dice.hs としてコピーする。

# mbplay に今いるとして
cp ../monad-bayes/models/Dice.hs src/

この~/test/mbplay/src/Dice.hs を使うために、~/test/mbplay/mbplay.cabalを書き換える。
srcディレクトリの下にあるモジュールファイルのうち、使うのはDice.hsであって、Lib.hsでは無いので、exposed-modulesを書き換える。

library  
  hs-source-dirs:      src
  exposed-modules:     Dice
  build-depends:       base >= 4.7 && < 5
                     , monad-bayes
  default-language:    Haskell2010

Main.hsを書き換える

さて。
Dice.hsを利用した処理を書く。
Dice.hsを使いつつ、それ以外にもいくつかのモジュールが必要でそれをimport指定しながら、

20個のサイコロを振って、その目の和を取ること、5000試行。

その結果をresultsに入れた後、
値ごとにソートして、隣同士で同じ値のものをグループ化して、その長さを求め、ヒストグラム様標準出力をさせている。

module Main where

import Dice
import Control.Monad.Bayes.Sampler

import Data.List (group, sort)
import Control.Monad (replicateM)

main :: IO ()
main = do
    results <- sampleIO . replicateM 5000 $ dice 20
    mapM_ putStrLn . hist . map length . group . sort $ results

-- create a very basic histogram. 
-- `div` 2 . (+1) is just there to make the bars shorter.
hist :: [Int] -> [String]
hist = map (flip replicate '#' . (`div` 2) . (+1))

実行してみよう

~/test/mbplay/

にて

stack build
stack exec mbplay-exec

練習を兼ねて少し改変

引数をとって、サイコロの数、試行回数、描出ヒストグラムの打点スケール、以上3つを指定するようにする

getArgsで取り込んだargs の0,1,2番目の要素をそれぞれInt型でnarg0,narg1,narg2に持たせる。

module Main where

import Dice
import Control.Monad.Bayes.Sampler

import Data.List (group, sort)
import Control.Monad (replicateM)

import System.Environment
import System.IO

main :: IO ()
main = do
    args <- getArgs
    let narg0 = read (args !! 0) :: Int
    let narg1 = read (args !! 1) :: Int
    let narg2 = read (args !! 2) :: Int
    results <- sampleIO . replicateM narg0 $ dice narg1
    --results <- sampleIO . replicateM 5000 $ dice 20
    --mapM_ putStrLn . hist . map length . group . sort $ results
    mapM_ putStrLn . (hist2 narg2) . map length . group . sort $ results

-- create a very basic histogram. 
-- `div` 2 . (+1) is just there to make the bars shorter.
hist :: [Int] -> [String]
hist = map (flip replicate '#' . (`div` 2) . (+1))

hist2 :: Int -> [Int] -> [String]
hist2 x = map (flip replicate '#' . (`div` x) . (+1))
stack build
stack exec mbplay-exe 100000 10 200
1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1