私は一般的な "how do you debug type-level programming problems?"という質問をしてみました。答えがあまりにも一般的なものか、そういうものをデバッグすることは不可能かもしれません。 : - }型シグネチャがあまりにも一般的です。制約がありませんか?
この特定の日に、私を悩ませている問題は、適度に大きい、複雑なプログラムです。私はまだそれが間違って合理的に小さなコアにそれを沸騰させることができた。ここに私達は行く:
{-#
LANGUAGE
GADTs, MultiParamTypeClasses,
FlexibleInstances, FlexibleContexts, RankNTypes,
KindSignatures
#-}
module Minimal where
-------------------------------------------------------------------------------
data Union (t :: * -> *) (ts :: * -> *) x
class Member (x :: * -> *) (ys :: * -> *) where
instance Member x (Union x ys) where
instance (Member x ys) => Member x (Union y ys) where
-------------------------------------------------------------------------------
data ActM (effects :: * -> *) x
instance Monad (ActM effects) where
-------------------------------------------------------------------------------
data Reader i x where
Get :: Reader i i
get :: Member (Reader i) req => ActM req i
get = undefined
runReader :: i -> ActM (Union (Reader i) req) x -> ActM req x
runReader = undefined
(脇:私は言語拡張のリストを見て、自分自身に考えて、「多分これはただひどいアイデアです!」)
とにかく、本当に興味深い部分がです下。私たちは、言い換えれば
runReader :: i -> ActM (Union (Reader i) req) x -> ActM req x
が、その可能性効果を任意のi
ため、runReader
が可能な効果の一つとしてReader i
を持ってActM
モナドでアクションを取り、なしActM
モナドでアクションを返すことがわかり。シンプル、そう?私は最初の引数として(例えば)Char
を渡した場合
さて、その後、リーダータイプがChar
に固定されています
runReader 'X' :: ActM (Union (Reader Char) req) x -> ActM req x
これまでのところ、とても良いです。私はいくつかのデータを返す場合は、すべての罰金です:
runReader 'X' (return True) :: ActM req Bool
(!安心させる、私はまた、結果として正しい値を取得)
しかし、今、何get
機能は?
get :: Member (Reader i) req => ActM req i
のでget
はReader i
が含ま効果の任意のセットのためのActM
モナドでのアクションです。そして、それは私がrunReader
に渡した場合、私は待って... ...
runReader 'X' get :: Member (Reader x) (Union (Reader Char) req) => ActM req x
を得ることを意味し、何?!?なぜコンパイラは、x
をにする必要がありますかと考えていませんでしたChar
?私は
runReader 'X' get :: ActM req Char
を言う明示的な型シグネチャを追加する場合
確かに、それは(ちなみに、私はいいです右の出力値を、取得、および)完全にコンパイルされます。だからどこに制約がありませんか?
インスタンス 'Member x(Union x ys)'は、両方の 'x 'が一致するためには同じでなければなりません。コンパイラはこの情報を推論しません。あなたは '(x〜x ')=>メンバーx(Union x' xs)'と書く必要がありますが、これは他のインスタンスと重複しています。 – user2407038
本当に十分な拡張機能ですか?それらの2つの 'Member'インスタンスはひどく疑わしいように見えます。おそらく、あなたは' OverlappingInstances'またはおそらく 'IncoherentInstances'が必要です。あなたがIncoherentInstancesを持っているなら、まあ...私は、その拡張子を持つ公式のパーティラインは、 "幸運、私たちに文句を言ってはいけない"と思う。 –
@DanielWagnerそれは奇妙です...「オーバーラップするインスタンス」がそこにあるはずです。どうやって行方不明になったのか分かりません。私は、私の最小限の例を構築している間にそれを誤って落としたはずです – MathematicalOrchid