アカウントは作ったものの一回もQiitaに投稿したことないので、
お試しがてら今思いついたアイデアをひとつ投下。
例えば
x : 文字列
n : 整数
c ::= () | True | False | n
e ::= c | Let x e e | If e e e
のように定義される式eに対応するASTを実装するにあたり、
Untyped/Typedな型が両方必要だとする。
(例えばパースした直後はUntypedだろうし、型付けする関数typingの型はtyping :: TypeEnv -> UntypedExpr -> TypedExprのようになるはず)
このようなときは子の型をパラメタで置き、ASTの親子構造だけ定義した型を作り、
それに実際にパラメタを渡して作ると綺麗に書ける。
具体的にはこんなん。
ast_struct.hs
type VarName = String
data Type = UnitT | BoolT | IntT | FunT Type Type
data ExprStruct child = UnitE | BoolE Bool | IntE Int | Var VarName | Let VarName child child | If child child child
data UntypedExpr = UExp (ExprStruct UntypedExpr)
data TypedExpr = TExp {expr::ExprStruct TypedExpr, typ::Type}
Untyped ASTはIf (BoolE True) UnitE UnitE
みたいに書けたらよかったけど、
type UntypedExpr = ExprStruct UntypedExpr
は流石に通らない。
(この辺うまくやる方法あったら教えてください……)