HaskellでMySQLの地理情報を扱いたい
まだコミットできるレベルにないけど、検証コードはできた。
Haskellで地理情報を扱うためにGeosパッケージのインストール(2018年02月時)
git
からモジュールを取得しておきます。
git clone https://github.com/ewestern/geos.git
開発中のライブラリから使用したいので、そのプロジェクトにて、普通にインストールしようとすると、geos
ライブラリが不足しているためエラーになりました。
$ cabal install geos Warning: --root-cmd is no longer supported, see https://github.com/haskell/cabal/issues/3353 (if you didn't type --root-cmd, comment out root-cmd in your ~/.cabal/config file) Resolving dependencies... Notice: installing into a sandbox located at /Users/.cabal-sandbox Downloading geos-0.1.1.1... Configuring geos-0.1.1.1... Failed to install geos-0.1.1.1 Build log ( /.cabal-sandbox/logs/ghc-8.0.1/geos-0.1.1.1-BMEKj1bfr4oGwvlkBjY7fl.log ): cabal: Entering directory '/var/folders/hw/p4bp49hd7v9_1j60sjvmhqnr0000gn/T/cabal-tmp-25906/geos-0.1.1.1' Configuring geos-0.1.1.1... cabal: Missing dependency on a foreign library: * Missing (or bad) header file: geos_c.h * Missing C library: geos_c This problem can usually be solved by installing the system package that provides this library (you may need the "-dev" version). If the library is already installed but in a non-standard location then you can use the flags --extra-include-dirs= and --extra-lib-dirs= to specify where it is. If the header file does exist, it may contain errors that are caught by the C compiler at the preprocessing stage. In this case you can re-run configure with the verbosity flag -v3 to see the error messages. cabal: Leaving directory '/var/folders/hw/p4bp49hd7v9_1j60sjvmhqnr0000gn/T/cabal-tmp-25906/geos-0.1.1.1' cabal: Error: some packages failed to install: geos-0.1.1.1-BMEKj1bfr4oGwvlkBjY7fl failed during the configure step. The exception was: ExitFailure 1
geos
をインストールします。
$ brew install geos Updating Homebrew... ==> Auto-updated Homebrew! Updated 3 taps (caskroom/cask, homebrew/core, homebrew/php). ==> New Formulae calicoctl dynare gpredict libdill odpi terraforming clblast fruit grv libsbol openimageio tomcat@8 dashing futhark homebrew/php/phpunit@6.5 ocrmypdf srt webtorrent-cli ==> Updated Formulae awscli ✔ c-ares emscripten git iperf3 libav node@6 plank statik acmetool camlp5 erlang git-archive-all irssi libpqxx ocaml postgresql@9.4 stlink advancecomp chakra etcd glpk jenkins liquibase ocaml-num qemu supervisor allure chronograf feh gnutls jenkins-lts logstalgia ocamlsdl qt suricata angular-cli cimg ffmpeg@2.8 go jfrog-cli-go lumo ooniprobe quicktype taisei aqbanking clhep fio godep joplin lynis opendetex recon-ng twarc aws-elasticbeanstalk console_bridge flow gomplate juju lzip osm2pgrouting rust typescript azure-cli coq fluent-bit googler just magic-wormhole paket rustup-init urdfdom bareos-client coreos-ct fn gource jvgrep mame pandoc-citeproc s-nail vala bazel dartsim forego grakn kallisto mariadb pc6001vx sagittarius-scheme vdirsyncer bcftools ddrescue freetds gtk+3 kedge mas pdns sbt@0.13 vim binaryen diamond frugal gutenberg knot math-comp percona-server@5.6 sceptre wtf bitrise dmd gcovr heroku knot-resolver mdcat pgpool-ii simg2img xtensor blast dnscrypt-wrapper gdnsd homebrew/php/envoy kobalt memcached picard-tools singular bro dub gecode homebrew/php/phpunit kompose metricbeat pilosa skafos buildapp duck geth hugo leptonica mpv pipenv sslh ==> Deleted Formulae homebrew/php/phpunit@5.7 tomcat@8.0 ==> Downloading https://homebrew.bintray.com/bottles/geos-3.6.2.yosemite.bottle.tar.gz ######################################################################## 100.0% ==> Pouring geos-3.6.2.yosemite.bottle.tar.gz 🍺 /usr/local/Cellar/geos/3.6.2: 402 files, 8.7MB
再度geos
をインストールするがヘッダファイルが見つからずエラーとなります。
$ cabal install geos Warning: --root-cmd is no longer supported, see https://github.com/haskell/cabal/issues/3353 (if you didn't type --root-cmd, comment out root-cmd in your ~/.cabal/config file) Resolving dependencies... Notice: installing into a sandbox located at /.cabal-sandbox Configuring geos-0.1.1.1... Building geos-0.1.1.1... Failed to install geos-0.1.1.1 Build log ( /Users/.cabal-sandbox/logs/ghc-8.0.1/geos-0.1.1.1-BMEKj1bfr4oGwvlkBjY7fl.log ): cabal: Entering directory '/var/folders/hw/p4bp49hd7v9_1j60sjvmhqnr0000gn/T/cabal-tmp-27304/geos-0.1.1.1' Configuring geos-0.1.1.1... Preprocessing library for geos-0.1.1.1.. Internal.hsc:9:10: fatal error: 'noticehandlers.h' file not found #include "noticehandlers.h" ^ 1 error generated. compiling dist/dist-sandbox-ce0620c0/build/Data/Geometry/Geos/Raw/Internal_hsc_make.c failed (exit code 1) command was: /usr/bin/gcc -c dist/dist-sandbox-ce0620c0/build/Data/Geometry/Geos/Raw/Internal_hsc_make.c -o dist/dist-sandbox-ce0620c0/build/Data/Geometry/Geos/Raw/Internal_hsc_make.o -m64 -fno-stack-protector -m64 -fno-stack-protector -m64 -D__GLASGOW_HASKELL__=800 -Ddarwin_BUILD_OS=1 -Dx86_64_BUILD_ARCH=1 -Ddarwin_HOST_OS=1 -Dx86_64_HOST_ARCH=1 -Icbits -fPIC -Idist/dist-sandbox-ce0620c0/build/autogen -Idist/dist-sandbox-ce0620c0/build/global-autogen -include dist/dist-sandbox-ce0620c0/build/autogen/cabal_macros.h -I/Users/.cabal-sandbox/lib/x86_64-osx-ghc-8.0.1/vector-0.12.0.1-JOtbAphig5lG2Gp1CUS1Dj/include -I/Users/.cabal-sandbox/lib/x86_64-osx-ghc-8.0.1/primitive-0.6.2.0-3HSsNCfUEEE4fjqDYVydYZ/include -I/Library/Frameworks/GHC.framework/Versions/8.0.1-x86_64/usr/lib/ghc-8.0.1/bytestring-0.10.8.1/include -I/Library/Frameworks/GHC.framework/Versions/8.0.1-x86_64/usr/lib/ghc-8.0.1/base-4.9.0.0/include -I/Library/Frameworks/GHC.framework/Versions/8.0.1-x86_64/usr/lib/ghc-8.0.1/integer-gmp-1.0.0.1/include -I/Library/Frameworks/GHC.framework/Versions/8.0.1-x86_64/usr/lib/ghc-8.0.1/include -I/Library/Frameworks/GHC.framework/Versions/8.0.1-x86_64/usr/lib/ghc-8.0.1/include/ cabal: Leaving directory '/var/folders/hw/p4bp49hd7v9_1j60sjvmhqnr0000gn/T/cabal-tmp-27304/geos-0.1.1.1' cabal: Error: some packages failed to install: geos-0.1.1.1-BMEKj1bfr4oGwvlkBjY7fl failed during the building phase. The exception was: ExitFailure 1
回避策として、ヘッダファイルを直接指定します。
$ cabal install geos --extra-include-dirs=/Users/geos/cbits 途中省略 [14 of 15] Compiling Data.Geometry.Geos.STRTree ( src/Data/Geometry/Geos/STRTree.hs, dist/dist-sandbox-d1b569cc/build/Data/Geometry/Geos/STRTree.o ) src/Data/Geometry/Geos/STRTree.hs:7:1: error: Failed to load interface for ‘Data.Geometry.Geos.Raw.STRTree’ Use -v to see a list of the files searched for. cabal: Leaving directory '/var/folders/hw/p4bp49hd7v9_1j60sjvmhqnr0000gn/T/cabal-tmp-48078/geos-0.1.1.1' cabal: Error: some packages failed to install: geos-0.1.1.1-GIstYXM1nrr5kUQOaLl4x4 failed during the building phase. The exception was: ExitFailure 1 $
Failed to load interface for ‘Data.Geometry.Geos.Raw.STRTree’
となってしまい、cabal
経由でのインストールは諦めました。先ほどclone
したところで、ライブラリを作ることとします。
ここで、geos.cabal
ファイルを修正します。たぶんData.Geometry.Geos.Raw.STRTree
の指定がother-modules
が必要なようです。
@@ -56,6 +58,7 @@ Library , Data.Geometry.Geos.Raw.Buffer , Data.Geometry.Geos.Raw.Prepared , Data.Geometry.Geos.Raw.Internal + , Data.Geometry.Geos.Raw.STRTree
使う側のプロジェクトにて
cabal sandbox add-source geos
をして、cabal
ファイルの依存関係に``geos```を追加ました。
これでコンパイルが通るようになりました。
関数のコンテキストの型はユニークに解決される
言われてみれば当たり前なのですが、これに嵌りました。
Num
型を複数とる関数があって、Int
型やDouble
型などいろいろパラメータに与えたかったのですが、コンパイルエラーがとれませんでした。問題点をシンプルな例で示すと以下のようになります。
Num
型を複数とる関数を定義します。数値のリストを2つとり、それぞれの要素を掛け合わせて、合計を取ります。
*Main> let sumtimes' = \xs ys -> sum $ zipWith (*) xs ys *Main> :t sumtimes' sumtimes' :: Num a => [a] -> [a] -> a
普通に動きます。
*Main> sumtimes' [1,2,3] [1,2,3] <interactive>:4:1: warning: [-Wtype-defaults] • Defaulting the following constraints to type ‘Integer’ (Num a0) arising from a use of ‘it’ at <interactive>:4:1-25 (Show a0) arising from a use of ‘print’ at <interactive>:4:1-25 • In the first argument of ‘print’, namely ‘it’ In a stmt of an interactive GHCi command: print it 14 *Main> sumtimes' [1.0,2.0,3.0] [1.0,2.0,3.0] <interactive>:5:1: warning: [-Wtype-defaults] • Defaulting the following constraints to type ‘Double’ (Fractional a0) arising from a use of ‘it’ at <interactive>:5:1-37 (Show a0) arising from a use of ‘print’ at <interactive>:5:1-37 • In the first argument of ‘print’, namely ‘it’ In a stmt of an interactive GHCi command: print it 14.0
型が曖昧で、ワーニングが出ていますが、型を明示的に指定すれば、ワーニングはなくなります。
*Main> sumtimes' [1::Int,2,3] [1,2,3] 14 *Main> sumtimes' [1,2,3] [1,2::Double,3] 14.0
ここまでは良いのですが、2つのバラメータに別の数値型のリストを与えた時は、コンパイルエラーになります。ここに気づかず時間を取られていまいました。
*Main> sumtimes' [1::Int,2,3] [1::Double,2,3] <interactive>:8:25: error: • Couldn't match expected type ‘Int’ with actual type ‘Double’ • In the expression: 1 :: Double In the second argument of ‘sumtimes'’, namely ‘[1 :: Double, 2, 3]’ In the expression: sumtimes' [1 :: Int, 2, 3] [1 :: Double, 2, 3] *Main>
Int
とInteger
でもコンパイルエラーになります。
*Main> sumtimes' [1::Int,2,3] [1::Integer,2,3] <interactive>:12:25: error: • Couldn't match expected type ‘Int’ with actual type ‘Integer’ • In the expression: 1 :: Integer In the second argument of ‘sumtimes'’, namely ‘[1 :: Integer, 2, 3]’ In the expression: sumtimes' [1 :: Int, 2, 3] [1 :: Integer, 2, 3] *Main>
Num a => [a] -> [a] -> a
の2つのパラメータは同じa
となっているので、同じ型でなければなりません。Nun
型のインスタンスならなんでもいいわけではありません。
git statusで追加したファイルが表示されない
新規に作成したファイルがgit status
で表示されず、少し焦りました。.gitignore
の指定対象になっていたようです。無理やりgit add``をしたところ、メッセージに教えてもらいました。
.gitignore```の設定を修正しました。
$ git add src/DataBase/MySQLX/ExprParser.hs The following paths are ignored by one of your .gitignore files: src/DataBase/MySQLX/ExprParser.hs Use -f if you really want to add them.
MySQLのサンプルデータベースのテーブル定義
いつも忘れるのでメモ
mysql-sql> use world_x; Query OK, 0 rows affected (0.01 sec) mysql-sql> show tables; +-------------------+ | Tables_in_world_x | +-------------------+ | city | | country | | countryinfo | | countrylanguage | +-------------------+ 4 rows in set (0.01 sec) mysql-sql> desc city; +-------------+----------+------+-----+---------+----------------+ | Field | Type | Null | Key | Default | Extra | +-------------+----------+------+-----+---------+----------------+ | ID | int(11) | NO | PRI | null | auto_increment | | Name | char(35) | NO | | | | | CountryCode | char(3) | NO | | | | | District | char(20) | NO | | | | | Info | json | YES | | null | | +-------------+----------+------+-----+---------+----------------+ 5 rows in set (0.09 sec) mysql-sql> desc country; +---------+----------+------+-----+---------+-------+ | Field | Type | Null | Key | Default | Extra | +---------+----------+------+-----+---------+-------+ | Code | char(3) | NO | PRI | | | | Name | char(52) | NO | | | | | Capital | int(11) | YES | | null | | | Code2 | char(2) | NO | | | | +---------+----------+------+-----+---------+-------+ 4 rows in set (0.01 sec) mysql-sql> desc countryinfo; +-------+-------------+------+-----+---------+------------------+ | Field | Type | Null | Key | Default | Extra | +-------+-------------+------+-----+---------+------------------+ | doc | json | YES | | null | | | _id | varchar(32) | NO | PRI | null | STORED GENERATED | +-------+-------------+------+-----+---------+------------------+ 2 rows in set (0.01 sec) mysql-sql> desc countrylanguage; +-------------+---------------+------+-----+---------+-------+ | Field | Type | Null | Key | Default | Extra | +-------------+---------------+------+-----+---------+-------+ | CountryCode | char(3) | NO | PRI | | | | Language | char(30) | NO | PRI | | | | IsOfficial | enum('T','F') | NO | | F | | | Percentage | float(4,1) | NO | | 0.0 | | +-------------+---------------+------+-----+---------+-------+ 4 rows in set (0.01 sec) mysql-sql>
Haskellのソースコードの言語拡張をいい感じにフォーマットする
Haskell
のコードの先頭に書くやつで、左側の({-#
)は揃ってるけど右側(#-}
)を揃える
{-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE TypeOperators #-} {-# LANGUAGE DataKinds #-} {-# LANGUAGE OverloadedLabels #-} {-# LANGUAGE RecordWildCards #-}
vim
でtabular
いれて、下記コマンド
:'<,'>Tabularize /#-}
Haskellでコンパイル時の特定のワーニングを抑制する
4.8. Warnings and sanity-checking
To turn off any warning, simply give the corresponding -fno-warn-... option on the command line.
repl
では、
> :set -fno-warn-unused-do-bind
でいけます。