テストを書いたら本体のバグが発覚しました,エラー時のレスポンスが捨てられてしまうのでhttpsJSONEitherは使わない,検索した内容をtwitterに投稿するものを作ろうと思います,string-transformの変換元にShow aを追加しました

テストを書いたら本体のバグが発覚しました

hspecを使ってshouldThrowを使っているのだけど,意図した例外を送出してくれないのかdid not get expected exceptionエラーになって困りました.

なんでだー???と思って調べたら本体コードがバグっていることがわかりました.非常に単純な変数の指定取り間違いでした…テストって大事ですね…

エラー時のレスポンスが捨てられてしまうのでhttpsJSONEitherは使わない

httpsJSONEitherを使うと,aesonで指定していないJSONのフィールドがレスポンスから省略されてしまうためエラー表示がわかりにくいので,あえてhttpsLBSでデータを取得してJSONのパースはdecodeで行うように変更しました.

google検索した内容を「検索しました」とtwitterに投稿するwebアプリケーションを作ろうと思います

前から欲しいと思っていたwebサービスをいい加減実装するかと思ったけどそもそもwebサービスである必要性がわからなくなってきた.内容はgoogle検索した内容を「検索しました」とtwitterに投稿するものです.

しかしこれ

  • webアプリケーション
  • ブラウザアドオン
  • mikutterプラグイン

のどれでも実現可能なので,webアプリケーションとして実装するべきなのかな…と悩んでいます.

それ以前にプロダクトの名前を思いつかないので開発に着手できない.google-search-post-twitterは機能名そのまますぎるし長過ぎますね…アクロニムにしてgsptで良いか…と思ったらgithubにerikdubbelboer/gspt: setproctitle() for Goがあったのでやめよう.

tweet-when-searchなら長さも許容範囲内?でもtはtwitter検索,wはwikipedia検索,sはstackageに割り当ててるからどれも頭文字をインスタント検索の1文字に割り当てられないんですよねーpipe…と思ったけどpはpixivだった.なんか使える単語ないかなーと思ってtweetで検索したらintentが出てきた,iは使ってないのでintent-search-tweetで良いかな.

開発にあたってservantを使おうかと思いましたがログイン画面をサクサク作りたいので結局yesodになりそう…

string-transformの変換元にShow aを追加しました

このパッケージは基本的には文字列たちの変換をサポートするものですが,他の言語のtoStringを考えると,Intなどの非文字列も文字列化出来た方が嬉しいですね.

別に追加しない理由もありませんし.

と思って適当に

instance Show a => ToString a where
    toString = show

してやったらエラー,まあ予想していました.例えばByteStringなんかはShowのインスタンスなので,上のByteStringだけに対するインスタンスか,Show a => ToString aのどちらを使えば良いのかわからなくなってしまいます.

OverlappingInstancesIncoherentInstancesを使えばこの問題を回避できます.インスタンス宣言と拡張機能 - #3(2009-12-03)

OverlappingInstancesは既に非推奨で,いくつかのプラグマに分かれています.とりあえずIncoherentInstancesを使ってみて解決しましたが,インスタンスに[incoherent]マークが付くんですね.

λ> :i ToString
class ToString a where
  toString :: a -> String
  {-# MINIMAL toString #-}
        -- Defined at /mnt/data/repo/string-transform/src/Data/String/Transform.hs:17:1
instance [incoherent] [safe] Show a => ToString a
  -- Defined at /mnt/data/repo/string-transform/src/Data/String/Transform.hs:35:10
instance [incoherent] [safe] ToString TL.Text
  -- Defined at /mnt/data/repo/string-transform/src/Data/String/Transform.hs:32:10
instance [incoherent] [safe] ToString T.Text
  -- Defined at /mnt/data/repo/string-transform/src/Data/String/Transform.hs:29:10
instance [incoherent] [safe] ToString BLU.ByteString
  -- Defined at /mnt/data/repo/string-transform/src/Data/String/Transform.hs:26:10
instance [incoherent] [safe] ToString BU.ByteString
  -- Defined at /mnt/data/repo/string-transform/src/Data/String/Transform.hs:23:10
instance [incoherent] [safe] ToString String
  -- Defined at /mnt/data/repo/string-transform/src/Data/String/Transform.hs:20:10

OverlappingInstancesの分かれたプラグマを使うのと,IncoherentInstancesを使うの,どちらが良いのだろうか?

危険なもの

GHC の型検査器は時々、ある種の問題を解決できない時に、言語拡張を有効にするように何気なく教えてくれま> す。それらの中にはこれが含まれます。

  • DatatypeContexts
  • OverlappingInstances
  • IncoherentInstances
  • ImpredicativeTypes

これらはたいてい設計上の欠陥を暗に示しています。GHC が使うように提案しているとしても、エラーをその場> で解決するために頼るのはやめましょう!

言語拡張 · shiatsumat/wiwinwlh-jp Wiki

そもそもこういう設計をすべきではなく,showShowに任せたほうが良いのかもしれない…

GHC/AdvancedOverlap - HaskellWikiを見るとclosed type familiesを使うという解決策もあるみたいですね.しかし,今回は別に型レベルプログラミングをしているわけではないので,この方法は使えなさそうです.

IncoherentInstancesを使っていいのか悩みましたがそんなに使うなと怒っているページは見つかりませんでしたし,safe haskellの範囲内で使えて普通に動くので使ってしまうことにしました.