シナリオは次のとおりです。タイプシグネチャを使用していくつかのコードを記述しましたが、GHCは一部のx
およびy
についてx〜yを推測できませんでした。通常、GHCにボーンをスローして、関数の制約に同型を追加することができますが、これはいくつかの理由で悪い考えです。
ケース3との戦いに数時間費やしました。 syntactic-2.0
で遊んでいます。そして、 NanoFeldspar.hs
で定義されたバージョンと同様に、ドメインに依存しないバージョンのshare
を定義しようとしました。 =。
私はこれを持っていました:
{-# LANGUAGE GADTs, FlexibleContexts, TypeOperators #-}
import Data.Syntactic
-- Based on NanoFeldspar.hs
data Let a where
Let :: Let (a :-> (a -> b) :-> Full b)
share :: (Let :<: sup,
Domain a ~ sup,
Domain b ~ sup,
SyntacticN (a -> (a -> b) -> b) fi)
=> a -> (a -> b) -> a
share = sugarSym Let
gHC could not deduce (Internal a) ~ (Internal b)
、これは確かに私が目指していたものではありません。そのため、意図しないコードを記述した(制約が必要)か、GHCが記述した他の制約のためにその制約を必要としていました。
(Syntactic a, Syntactic b, Syntactic (a->b))
を制約リストに追加する必要がありましたが、いずれも(Internal a) ~ (Internal b)
を意味していません。基本的に正しい制約につまずいた。それらを見つける体系的な方法はまだありません。
私の質問は:
Internal a ~ Internal b
がないので、GHCはどこからそれを引き出しましたか?まず、関数の型が間違っています。 (コンテキストなしで)a -> (a -> b) -> b
であるべきだと確信しています。 GHC 7.10は、元のコードでは制約Internal (a -> b) ~ (Internal a -> Internal a)
が欠落していると文句を言うため、それを指摘するのに多少役立ちます。 share
のタイプを修正した後、GHC 7.10は引き続きガイドとして役立ちます。
Could not deduce (Internal (a -> b) ~ (Internal a -> Internal b))
上記を追加すると、Could not deduce (sup ~ Domain (a -> b))
が得られます
それを追加すると、Could not deduce (Syntactic a)
、Could not deduce (Syntactic b)
、Could not deduce (Syntactic (a -> b))
が得られます
これら3つを追加すると、最終的に型チェックが行われます。だから私たちは
share :: (Let :<: sup,
Domain a ~ sup,
Domain b ~ sup,
Domain (a -> b) ~ sup,
Internal (a -> b) ~ (Internal a -> Internal b),
Syntactic a, Syntactic b, Syntactic (a -> b),
SyntacticN (a -> (a -> b) -> b) fi)
=> a -> (a -> b) -> b
share = sugarSym Let
ですから、GHCは私たちを導くのに役に立たなかったとは思いません。
GHCが制約要件を取得する場所のトレースに関する質問については、 GHCのデバッグフラグ 、特に-ddump-tc-trace
を試してから、結果のログを読んでInternal (a -> b) ~ t
と(Internal a -> Internal a) ~ t
が追加されている場所を確認できますWanted
を設定しますが、それは非常に長い読み取りになります。