Mac/emacsでHaskell環境を作る
最近会社でHaskell書くタスクがあがってきたので環境を作っていた。
最近sublimtext2ばかり使っていたのだが、haskellはかなり文法がかなり厳密な言語なのでflymake(シンタックスチェッカ)がないと辛い
Haskellのインストール
最近のMac(Lion)は標準だとllvmでないgccは持ってないので以下のリンクからDLしてくる
https://github.com/kennethreitz/osx-gcc-installer
LLVMに対応していないので、Macデフォルトのgcc(llvm-gcc)は使えない
Haskellのバイナリをもらってくる
http://hackage.haskell.org/platform/
Homebrewにもあるが、自前のビルドはかなり時間がかかる
Haskellのパッケージマネージャのcabalは /Developer/usr/bin/gcc を見ようとするのだが、Lion以降のMacは/Developer廃止されてるので、適当にaliasだけ作っておく
$ sudo mkdir -p /Developer/usr/bin $ sudo ln -s /usr/bin/gcc-4.2 /Developer/usr/bin/gcc
cabal で hlint いれておく。よりよいメソッドの提案などをしてくれる。
$ cabal install happy $ cabal install haskell-src-exts $ cabal install hlint
hlint かなり賢いので困ったら頼るといい
Haskell-mode
最近はすべてel-getで管理するようにしている。
dimitri/el-get https://github.com/dimitri/el-get
(あとでel-getについてもまとめた記事を書きたい)
とりあえず実行してみる
ghciでREPL起動
$ ghci GHCi, version 7.0.4: http://www.haskell.org/ghc/ :? for help Loading package ghc-prim ... linking ... done. Loading package integer-gmp ... linking ... done. Loading package base ... linking ... done. Loading package ffi-1.0 ... linking ... done. Prelude> print $ 3 * 7 21 Prelude>
Hello.hs
putStrLn "Hello, Haskell"
runhaskellで実行
$ runhaskell Hello Hello, Haskell
emacs
主にflymakeの設定
(el-get-install "haskell") ;call once (load "~/.emacs.d/el-get/haskell-mode/haskell-site-file") (require 'flymake) (global-set-key (kbd "M-n") 'flymake-goto-next-error) (global-set-key (kbd "M-N") 'flymake-goto-prev-error) (defun flymake-Haskell-init () (flymake-simple-make-init-impl 'flymake-create-temp-with-folder-structure nil nil (file-name-nondirectory buffer-file-name) 'flymake-get-Haskell-cmdline)) (defun flymake-get-Haskell-cmdline (source base-dir) (list "ghc" (list "--make" "-fbyte-code" (concat "-i"base-dir) source))) (defvar multiline-flymake-mode nil) (defvar flymake-split-output-multiline nil) (defadvice flymake-split-output (around flymake-split-output-multiline activate protect) (if multiline-flymake-mode (let ((flymake-split-output-multiline t)) ad-do-it) ad-do-it)) (defadvice flymake-split-string (before flymake-split-string-multiline activate) (when flymake-split-output-multiline (ad-set-arg 1 "^\\s *$"))) (add-hook 'haskell-mode-hook '(lambda () (add-to-list 'flymake-allowed-file-name-masks '("\\.l?hs$" flymake-Haskell-init flymake-simple-java-cleanup)) (add-to-list 'flymake-err-line-patterns '("^\\(.+\\.l?hs\\):\\([0-9]+\\):\\([0-9]+\\):\\(\\(?:.\\|\\W\\)+\\)" 1 2 3 4)) (set (make-local-variable 'multiline-flymake-mode) t) (if (not (null buffer-file-name)) (flymake-mode)) ))
わざとシンタックスエラーを起こしてflymake-goto-next-errorするとこうなる
これでストレスなくなりました