vscode + Haskell IDE Engine の組み合わせで Haskell を書き続けて半年ぐらいになります。
Haskell
hie が採用している整形ツールは brittany なのですが、個人的には hindent よりも気に入っています。(最近 Add import and module support #124 が実装されたんですけど、この部分は正直気に入っていない・・・。stylish-haskell の結果の方が好きです。)
hie
stylish-haskell
今回のバグはコード整形時にファイルの最後に空行が追加されてしまうというものでした・・・。(100回実行すると100行追加されます・・・)
上記の issue が Fix extra newline being added when formatting document #525 で修正されました。
issue
手作業で毎回削除してて、絶対何かおかしいと思ってましたが、ちゃんと直りました!!!やったね!
以上です。
LiquidHaskell では measure という仕組みを使って Haskell の関数を LH の述語に持ち上げることができます。
LiquidHaskell
measure
LH
しかし、以下の nLen 関数は measure によって持ち上げることができません。
nLen
{-@ measure nLen @-} nLen :: [Int] -> Int nLen [] = 0 nLen (n:ns) = n + nLen ns
結論から言えば、これを解決するためには --prune-unsorted フラグを利用します。
--prune-unsorted
以下は measure の基本的な使い方等についての説明です。
難易度: λλλ
以下の Conduit を使ったコードの実行結果を予想してみてください!
Conduit
#!/usr/bin/env stack -- stack script --resolver lts-11.3 import Conduit main :: IO () main = print $ runConduitPure $ return () .| do mapM_ leftover [1..10] sinkList
答えは次回。
難易度: λλ
#!/usr/bin/env stack -- stack script --resolver lts-11.3 import Conduit myTakeWhileC :: Monad m => (i -> Bool) -> ConduitM i i m () myTakeWhileC f = loop where loop = do mx <- await case mx of Nothing -> return () Just x | f x -> yield x >> loop | otherwise -> return () main :: IO () main = print $ runConduitPure $ yieldMany [1..10] .| do x <- myTakeWhileC (<= 5) .| sinkList y <- sinkList return (x, y)
#!/usr/bin/env stack -- stack script --resolver lts-11.2 import Conduit trans :: Monad m => ConduitM Int Int m () trans = do takeC 5 .| mapC (+ 1) mapC (* 2) main :: IO () main = runConduit $ yieldMany [1..10] .| trans .| mapM_C print
最近は Conduit にはまっているので、クイズも Conduit が続きます。
#!/usr/bin/env stack -- stack script --resolver lts-11.0 import Conduit sink :: Monad m => ConduitM Int o m (String, Int) sink = do x <- takeC 5 .| mapC show .| foldC y <- sumC return (x, y) main :: IO () main = do let res = runConduitPure $ yieldMany [1..10] .| sink print res
今回は prettyprinter を使ってみました。
使おうと思ったモチベーションとしては、以下のようなデータ型をデバッグ表示させる際に prettyprinter 系パッケージを使って良い感じに表示してみようかな?という感じです。
prettyprinter
data Person = Person Text String
表示をカスタマイズするために Show クラスのインスタンスを書き換えることは、経験上嫌なことしか起きないです・・。
Show
自分でそれっぽい型クラスを作っても良いのですが、普通は素直に prettyprinter 系のパッケージを使った方が良いと思います!
$ stack repl --package text Prelude> import Data.Text Prelude Data.Text> data Person = Person Text String deriving Show Prelude Data.Text> :set -XOverloadedStrings Prelude Data.Text> Person "はすける" "らむだ" Person "\12399\12377\12369\12427" "\12425\12416\12384"
難易度: λ
今回は、与えられた値がリストのリストに含まれているかどうかを判定する問題です。
幅優先で探索する関数 bfs と深さ優先で探索する関数 dfs をそれぞれ定義してみましょう。
bfs
dfs
bfs :: Int -> [[Int]] -> Bool bfs = undefined dfs :: Int -> [[Int]] -> Bool dfs = undefined
実行結果はだいたいこんな感じです。
$ stack repl -- Quiz4.hs *Quiz4> xs = [[10..],[4,5,6],[7,8,9]] *Quiz4> bfs 9 xs True *Quiz4> dfs 9 xs .....
propIsDigit テストをパスするように Digit 型の Arbitrary インスタンスを定義してみましょう。
propIsDigit
Digit
Arbitrary
module Quiz3 where import Test.QuickCheck import Data.Char (isDigit) newtype Digit = Digit Char deriving Show propIsDigit :: Digit -> Bool propIsDigit (Digit c) = isDigit c instance Arbitrary Digit where arbitrary = undefined
テストは以下のように実行します。
$ stack repl --package QuickCheck -- Quiz3.hs *Quiz3> quickCheck propIsDigit +++ OK, passed 100 tests.
上記のように OK になれば (たぶん) 正解です!
OK
ヒント: 生成される値をデバッグしたい場合は sample' 関数が便利です。
sample'
*Quiz3> sample' (arbitrary :: Gen Digit)
HIE (Haskell IDE Engine) を Emacs に導入する方法が HIE の README.md に追記されたので、それに従いインストールしてみました。
Emacs
HIE
本記事では、導入手順を紹介します。
foldr (&&) True $ cycle [True, False] foldl (&&) True $ cycle [True, False]
上記の2つの式の挙動の違いを説明してください。
また、なぜそうなるのか考えてみましょう!
何となくクイズはじめました!(頑張って続けます・・・)
間違ってたら twitter や github の issue で教えてください!
twitter
今回は gitrev パッケージと optparse-simple パッケージを使ってアプリケーションに Git の情報を含めてみようと思います!
Git
利用者の多いアプリケーションだと、バグ報告時にどのコミットでビルドしたものなのか知りたい場合に便利です。
表示されるバージョン情報はこんな感じになります。
# gitrev の例 $ ./Main.hs Main.hs: [panic master@3a0bd17fdfb8a3e334292a560280e8e0791e941c (Tue Mar 20 02:00:17 2018 +0900) (1 commits in HEAD)] # optparse-simple の例 $ stack exec -- example-version-exe Version 0.1.0.0, Git revision 341e785b02c4c599f64b922b4aa9cfff3c006945
以下のアプリケーション等でも利用されているように、実用度はとても高めです。
また、実装コストもそれほどかからないため、オススメです!
今回は Yesod を使っているマニア向け情報です。
Yesod
Yesod にはサブサイトという機能があり、Yesod Book の Creating a Subsite で一通りの使い方が説明されています。
簡単に言えば、異なる Yesod アプリケーションで共通のコンポーネント (認証システム等) を利用するために使えるようです。
scaffolded site を使っている人は yesod-static パッケージで提供されている Static 型をサブサイトとして利用していることでしょう。
scaffolded site
Static
Yesod のバージョンが 1.6 に上がった影響により Yesod Book の内容がそのままでは動かなくなっていたため、コードを修正して実際に動かしてみたいと思います。
1.6
Yesod Book
今日マージされた Allow ‘github’ shorthand for extra-deps (fixes #3873) #3890 がとても便利だと思いますのでご紹介します。
$ stack --version Version 1.7.0, Git revision 4a140342f9b28005bf2fdd5335bdcd32c9370265 (5702 commits) x86_64 hpack-0.21.2
Liquid Haskell を半年ほど勉強した結果、色々と出来ることが増えて楽しくなってきました。
Liquid Haskell
現状、日本語で詳しく説明しているブログ記事や Qiita 記事はほとんどありません。
Qiita
とても面白いツールだと思いますので、色々と紹介していけたらと思います。
今回は Liquid Haskell の導入方法について簡単に説明したいと思います。
Liquid Haskell で少しハマったのでメモとして残しておきます。
本来なら先に仕様を書いて実装を書くべきだと思いますが、今回の例は既存のコードにリファインメント型をつけるような場合を想定しています。
$ liquid LiquidHaskell Version 0.8.2.4, Git revision d641244775cd842776cecf2c5d3e9afa01549e76 (dirty) Copyright 2013-18 Regents of the University of California. All Rights Reserved.
Liquid Haskell を気になってる人向けの記事です。
僕は stack, hlint, liquidhaskell などのパッケージを毎日なんとなくビルドしてインストールしているのですが、ある時 stack のビルドで GHC panic が発生し、ビルドができなくなってしまいました。
stack
hlint
liquidhaskell
GHC panic
数日放置していたのですが、直らず・・・。そればかりか別のPCでは問題なくビルドができているため stack の問題だな!と意気揚々と issue を作ったのですが、結局は自分の環境の問題でした・・・。
僕は英語が得意ではありませんが、こういった時に批判だけするのは良くないと思っているので、頑張って issue や PR を投げるようにしています。Google 翻訳とかもありますし、誰か助けてくれますよ、きっと。 (放置されたり却下されることもありますが、気にせずコツコツ続けると楽しいです)
PR
先日 Stack version 1.6.5 がリリースされました。
バグフィックスのみです。
いくつか前回の 1.6.3 に含まれていた内容が 1.6.5 に移動してますね。
persistent ライブラリで SomeField を CopyField に置き換える際のPRで、パターンシノニム (Pattern Synonyms) の面白い使い方を見つけました。
persistent
SomeField
CopyField
もしかしたら良く知られた技なのかもしれませんが、ご紹介したいと思います。
パターンシノニムが何かについての説明は、今回全くしていませんのでわかる人向けです。
HLint は haskell-src-exts を使って実装されている静的解析ツールです。
HLint を使えば github などを使って PR ベースで開発する場合のコードレビューでこんな事を言わなくて済みます。
HLint
github
fromJust
maybe
undefined
嬉しいことに Travis CI や CircleCI などで一度設定するだけなので導入もお手軽です! また、最近知ったのですが、プロジェクト内で使って欲しくない関数なども HLint によって検出可能です。
Travis CI
CircleCI
さらに、独学で Haskell の学習を進めている人は HLint が素晴らしい教師役となってくれるでしょう。
ここ最近、プロジェクトのビルド時に謎のエラーが発生するようになりました。
以下の2種類のエラーに遭遇したので、今後のために記録しておきます。
pthread link error
-fPIC error
$ stack --version Version 1.7.0, Git revision 19e3460496f8fd2c462fb35a5825301e5c3c4eb0 (5527 commits) x86_64 hpack-0.20.0
travis-ci の初回ビルド時に以下のようなエラーメッセージが表示されてビルドに失敗してしまうことがあります。
travis-ci
The command "stack --no-terminal test --only-dependencies" failed and exited with 1 during . Your build has been stopped.
結論から言えば、初回ビルド時はキャッシュが働かないため、多くの依存関係をビルドする必要があり、その過程でメモリ不足になってしまっていました。
この問題をどうすれば解決できるか、メモ程度に残しておこうと思います。
今回は Literate Markdown をご紹介します。(最近見つけて面白そうだったので使ってみました。)
Literate Markdown
モチベーションとしては Bird 記法や TeX 記法だけではなく、Markdown 記法も使いたいよね!という感じです。
Bird
TeX
Markdown
また、HaskelL の文学的 (Literate) プログラミングについては、すでに多くのWeb・書籍等で言及されているため、必要最低限の説明に留めたいと思います。
HaskelL
本記事の内容は以下を参考としています。
Grid Table 記法の紹介
以下のコマンドで stack v1.6.3 のバイナリが落ちてきます。
stack v1.6.3
$ stack upgrade
機能追加は無く、改良とバグフィックスのみです。
stack ls コマンドは今回に含まれていないので v1.7.0 で追加されそうな感じですね。
stack ls
v1.7.0
ちょっと前に version 1.6.1 がリリースされたので、その中の目玉機能でもある カスタムスナップショット を紹介したいと思います。
カスタムスナップショット
Stack の master に stack ls コマンドがマージされました。
Stack
master
今後、このコマンドのサブコマンドに list-dependencies などを順次追加していく方針?のようです。
list-dependencies