4

今日私が以前に尋ねたこの質問に関連しています。

「注釈」タイプによってパラメーター化された、多数のケースを持つ AST データ型があります。

data Expr ann def var = Plus a Int Int
    | ...
    | Times a Int Int
    deriving (Data, Typeable, Functor)

def と var の具体的なインスタンスがDefありVarます。

私が望むのはfmap、最初の引数でファンクターとして機能するものを自動的に導出することです。次のような関数を導出したいと思います。

fmap :: (a -> b) -> (Expr a Def Var) -> (Expr b Def Var)

normal を使用するfmapと、fmap がその関数を最初ではなく最後の型引数に適用しようとしていることを示すコンパイラ メッセージが表示されます。

定型文をたくさん書かずに、説明されているように関数を派生させる方法はありますか? 私はこれをやってみました:

newtype Expr' a = E (Expr a Def Var)
    deriving (Data, Typeable, Functor)

しかし、次のエラーが表示されます。

  Constructor `E' must use the type variable only as the last argument of a data type

私は他の誰かのコード ベースで作業しているので、どこでも型引数の順序を切り替える必要がなければ理想的です。

4

2 に答える 2

4

Functor簡単に言えば、変化する型変数が最後の位置にある必要があるため、これは不可能です。種類の型コンストラクターのみがインスタンス* -> *を持つことができ、あなたにはその種類がありません。FunctorExpr

Functorインスタンスは本当に必要ですか?fmap のような関数を書く定型文を避けたいだけなら、SYB のようなものがより良い解決策です (ただし、定型文はそれほど悪くなく、一度しか書けないでしょう)。

Functor他の理由で必要な場合(おそらく、このデータ構造をFunctor制約付きの関数で使用したい場合)、現在の順序でインスタンスまたは型変数のどちらを使用するかを選択する必要があります。

于 2014-12-28T08:54:06.660 に答える