残念ながら、これは実際には不可能です。a はMonad
完全にポリモーフィックでなければなりません。Set
モナド (Ord
制約)を作成できないのと同じ理由です。
結果の型が制約を満たすことだけに対処できる場合はrunSQL :: (Product a) => SQL a -> IO a
、 、または同様のものを持つことができます。その場合、適切なインスタンスを Template Haskell で導出するか、代わりに新しいGHC Genericsを使用する方法です。単純な Haskell には、型が積だけで構成されているかどうかを判断する方法がありません。
しかし、モナド計算を SQL に変換するには、モナド計算の構造全体にアクセスする必要があると思います。残念ながら、モナドは「内部を見る」ことができない任意の Haskell 関数と一緒にプラグインされているため、これにはあまり適していません。矢印は近くにあり、より多くの静的分析を行うことができますが、それでもarr
任意の Haskell 関数に忍び込むことができる厄介な点があります。
このようなことを行うための最も実行可能なオプションは、おそらくテンプレート Haskell スプライサーを作成して、必要な構文を解析することです。コンパイル時に AST を対応する SQL に変換することができます。その構文があまりにも醜い場合は、haskell-src-meta で quasiquoter を使用すると、次$(sql [| [ (a,b) | a <- table1, b <- table2 |])
のようになります。sql
[sql| (a, b) | a <- table1, b <- table2 |]
一般化された矢印拡張にも興味があるかもしれませんが、それはおそらくあなたの目的にはやり過ぎです (そしてあまりにも実験的です)。