私はHaskellで型表現された式パーサーを作成しようとしていますが、これはこれまで素晴らしいですが、現在は高次関数を実装しようとしています。私は簡単な例まで問題を煮ました:型付き式パーサー
{-# LANGUAGE TypeFamilies,GADTs,FlexibleContexts,RankNTypes #-}
-- A function has an argument type and a result type
class Fun f where
type FunArg f
type FunRes f
-- Expressions are either constants of function applications
data Expr a where
Const :: a -> Expr a
App :: Fun f => f -> FunArg f -> Expr (FunRes f)
-- A very simple function
data Plus = Plus
-- Which takes two integer expressions and returns an integer expression
instance Fun Plus where
type FunArg Plus = (Expr Int,Expr Int)
type FunRes Plus = Int
-- A more complicated function which lifts a function to lists (like in haskell)
data Map f r = Map f
-- For this we need the concept of lifting function arguments:
class Liftable a where
type LiftRes a
-- A singleton argument is lifted by changing the expression type from a to [a]
instance Liftable (Expr a) where
type LiftRes (Expr a) = Expr [a]
-- Two function arguments are lifted by lifting each argument
instance (Liftable a,Liftable b) => Liftable (a,b) where
type LiftRes (a,b) = (LiftRes a,LiftRes b)
-- Now we can declare a function instance for Map
instance (Fun f,Liftable (FunArg f),r ~ LiftRes (FunArg f)) => Fun (Map f r) where
type FunArg (Map f r) = r
type FunRes (Map f r) = [FunRes f]
-- Now a parser for functions:
parseFun :: [String] -> (forall f. Fun f => f -> a) -> a
-- The parser for the plus function is easy:
parseFun ["plus"] f = f Plus
-- But the parser for map is not possible:
parseFun ("map":sym) f
= parseFun sym (\fun -> f (Map fun))
問題は、再帰的なクラス宣言が禁止されているので、すべてのLiftRes自体が昇降可能である型チェッカーを説得する方法がないということのようです。
私の質問は次のとおりです。この作業を行うにはどうすればよいですか?私はヒントを取ることができる型付き式パーサの他の例がありますか?
編集:this discussion about type family constraintsは非常に関連しているようです。しかし、私のソリューションは、私の場合にはうまくいかず、誰かがそれを手伝ってくれるかもしれません。
機能クラスに 'Liftable'制約を追加することの問題点は、これがその後、昇降'のインスタンスが必要ですMapインスタンスに '昇降r'を追加するために私を必要とすることである(LiftResを(FunArg F))'パーサーでこのプロセスは、無期限に継続することができます。 あなたの発言について:実際のコードでは、私はlisp式を構文解析していますが、追加のパッケージをインストールする必要はありません。 – henning
ありがとう、これは他のポストも(私は思う)取得しているものです。しかし、私はあなたのコードを動作させることができない、それは前と同じエラーメッセージを与えます。私は他の何かを変えなければなりませんか?または私はいくつかのコンパイラフラグなどがありませんか? – henning
私はこのすべてをどのように使っているのか推測できます。実際のエラーがあなたの例で再現できない場合は、あなたのシナリオで実際に動作するものを提案するのは難しいです。 – kosmikus