コンテキストの順番を入れ換えると互換性が崩れることがある

(注:この記事はかなり前に書いて公開し忘れていたことに今日気付いたものです.もう当たり前になってるかもしれないけどもったいないので一応)

ghc8以降TypeApplications拡張が入ったこともあり一応の注意喚起.

たとえば,次のように関数fとgを定義する.時系列的にはfの型をgの型に変更したような想定で.

data X a b = X a b

f :: (Show a, Show b) => X a b -> String
f (X a b) = show a ++ show b

-- fと比べて型変数aとbに対するShowコンテキストを入れ換えたもの
g :: (Show b, Show a) => X a b -> String
g = f

普通に使っている分にはfからgの変更に問題無い.

x :: X Int Char
x = X 1 '0'

fx :: String
fx = f x

gx :: String
gx = g x

だけど,TypeApplications付けて使ってる箇所は型検査に失敗する.

{-# LANGUAGE TypeApplications #-}

fx :: String
fx = f @Int x

gx :: String
gx = g @Int x -- Error

といったように,コンテキストの順番変更も型の変化に相当する場合がある.また,コンテキストを減らすことができるケースであっても,それにより型変数の出現順が変わるとTypeApplicationsにより型検査に失敗するようになることがある.

互換性破壊してるのにhackageバージョニングポリシに従ったバージョン上げを行っていないライブラリをアップロードしてしまうことになるかもしれないので,ライブラリ作者はTypeApplications拡張の存在も気にして互換性の管理をするべきだと思われる.逆に,ライブラリ利用者としてはTypeApplications拡張使っているとこういう漏れてきた互換性破壊を踏んでしまうかもしれないという認識を持つべきなのかな.